使用鼠标选择轮廓

Picking contours using the mouse?

本文关键字:轮廓 选择 鼠标      更新时间:2023-10-16

我的项目采用给定窗口的客户端区域的位图快照,并将该数据转换为IplImage实例。然后经过灰度转换,脱粒等,在超过给定最小尺寸(面积体积)的任何轮廓周围绘制边界框。
然后在cvNamedWindow

中显示结果。

我现在所需要做的就是允许用户在这些矩形内单击以有效地"选择"该轮廓,以便应用程序可以将子矩形提取为新图像并将其保存到磁盘。

如何在c++中使用OpenCV来实现这一点?

如果您存储了边界框,则可以在鼠标事件处理程序中的for循环中检查是否单击了某个框以及单击了哪个框。创建鼠标事件的代码:

cvNamedWindow("MyWindow", CV_WINDOW_NORMAL);
cvSetMouseCallback("MyWindow", mouseEvent, 0);
imshow("MyWindow", image);
void mouseEvent(int evt, int x, int y, int flags, void *param) {
    if (evt == CV_EVENT_LBUTTONDOWN) {
        printf("%d %dn", x, y);
    }
}

你可以自己找出如何检查这些坐标是否在一个边界框内。我还建议使用c++ API,如评论中所述,因为一旦你掌握了它的窍门,它就会容易得多。

如果有人对如何实际提取所选图像感兴趣,
我是这样做的:

inline
IplImage* getSubImage(IplImage *image, CvRect region)
{
    cvSetImageROI(image, region);
    IplImage *imgRet = cvCreateImage( cvSize(region.width, region.height), image->depth, image->nChannels );
    cvCopy(image, imgRet);
    cvResetImageROI(image);
    return imgRet;
}
inline
bool pointInRect(const int x, const int y, const CvRect& r)
{
    return (
        (x > r.x) && (x < (r.x + r.width)) &&
        (y > r.y) && (y < (r.y + r.height))
    );
}
void onMouseEvent(int evt, int x, int y, int flags, void *param)
{
    if (evt == CV_EVENT_LBUTTONDOWN) {
        // boundingBoxes is declared as a vector of CvRects and
        //    filled in the main loop using cvBoundingRect(contour)
        for(UINT i = 0; i < boundingBoxes.size(); i++)
        {
            CvRect rect = boundingBoxes[i].rect;
            if( pointInRect(x, y, rect) )
            {
                IplImage* img = getSubImage(imgSource, rect);
                // Do whatever you want with the sub-image here
                cvNamedWindow("Selection");
                cvShowImage("Selection", img);
                cvReleaseImage(&img);
                break;
            }
        }
    }
}