RectangleEquals
RectangleEquals

Reputation: 1825

Picking contours using the mouse?

My project takes a bitmap snapshot of the client area of a given window, and converts this data into an IplImage instance. Then after a grayscale conversion, threshing etc, bounding boxes are drawn around any contours which exceed a given minimum size (area volume).
The result is then shown within a cvNamedWindow

All I need to do now is allow the user to click within these rects to effectively "choose" this contour, so that the application can then extract the subrect as a new image and save it to disk.

How can this be achieved using OpenCV in C++?

Upvotes: 1

Views: 871

Answers (2)

RectangleEquals
RectangleEquals

Reputation: 1825

In case anyone else was interested on how to actually extract the chosen image,
here's how I was able to do it:

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;
            }
        }
    }
}

Upvotes: 0

thomas_haximus
thomas_haximus

Reputation: 1531

If you store your bounding boxes you can check in a for loop in a mouse event handler if a box is clicked and which box is clicked. The code for creating a mouse event:

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 %d\n", x, y);
    }
}

You can probably find out yourself how to check if these coordinates are within a bounding box. I would also recommend to use the C++ API, as stated in the comments, as it is much easier once you get the hang of it.

Upvotes: 2

Related Questions