我是图像处理的新手。我注意到你可以在像opencv这样的图像处理库中指定rectangular region of interest和其他像circles等。像ms-paint这样的基本绘图程序包含了自由格式选择,但我似乎找不到关于如何在opencv或其他图像处理库中进行自由格式图像选择的功能或教程。关于如何实现这一点的任何想法? PS:我的首选语言是c / c ++。
答案 0 :(得分:3)
你可以尝试一件事:
如果选择可以表示为2d向量序列,则可以将其视为多边形。分配一个新的1通道图像作为你的面具并用0填充。然后使用
void cvFillPoly(CvArr* img, CvPoint** pts, int* npts, int contours, CvScalar color, int lineType=8, int shift=0)
记录在
http://opencv.willowgarage.com/documentation/drawing_functions.html
在蒙版图像上绘制非零区域,以表示图像的选定部分。
答案 1 :(得分:1)
我写了一个演示来显示图像并在鼠标移动时画出小绿点,见下文。
你需要知道 OpenCV不是为这种类型的交互而设计的,所以性能是个问题(而且很糟糕)!你会明白我的意思。
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
// mouse callback
void on_mouse(int event, int x, int y, int flags, void* param)
{
// Remove comment below to paint only when left mouse button is pressed
//if (event == CV_EVENT_LBUTTONDOWN)
{
//fprintf(stderr, "Painting at %dx%d\n", x, y);
IplImage* img = (IplImage*)param;
cvCircle(img, cvPoint(x,y), 1, CV_RGB(0, 255, 0), -1, CV_AA, 0);
cvShowImage("cvPaint", img);
}
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
fprintf( stderr, "Usage: %s <img>\n", argv[0]);
return -1;
}
IplImage* frame = NULL;
frame = cvLoadImage(argv[1], CV_LOAD_IMAGE_UNCHANGED);
if (!frame)
{
fprintf( stderr, "Failed: Couldn't load file %s\n", argv[1]);
return -1;
}
cvNamedWindow("cvPaint", CV_WINDOW_AUTOSIZE);
cvShowImage("cvPaint", frame);
cvSetMouseCallback("cvPaint", &on_mouse, frame);
while (1)
{
// Keep looping to prevent the app from exiting,
// so the mouse callback can be called by OpenCV and do some painting
char key = cvWaitKey(10);
if (key == 113 || key == 27) // q was pressed on the keyboard
break;
}
cvReleaseImage(&frame);
cvDestroyWindow("cvPaint");
return 0;
}
我的建议是你使用其他窗口系统进行此类任务,其中性能更好。例如,看看 Qt 。但是,如果您愿意,也可以使用 win32 或 X 等原生方式进行平台。
对于问题的其他部分,如何裁剪用户选择,我建议您查看以下代码:OpenCV resizing and cropping image according to pixel value
此外,在用户绘制图像时记录鼠标坐标比分析绘制绿点的图像更加实用。然后分析这些坐标并从中检索最小的矩形区域。这就是这个逻辑变得有用的时候了:
CvScalar s;
for (x=0; x<width-1; x++)
{
for(y=0; y<height-1; y++)
{
s = cvGet2D(binImage, y, x);
if (s.val[0] == 1)
{
minX = min(minX, x);
minY = min(minY, y);
maxX = max(maxX, x);
maxY = max(maxY, y);
}
}
}
cvSetImageROI(binImage, cvRect(minX, minY, maxX-minX, maxY-minY));
在这种特定情况下,您不会迭代图像来查找用户在该问题中所做的特定像素,而是迭代鼠标移动过程中记录的坐标数组。