使用鼠标从video上的矩形设置ROI

我有video,当程序运行时,video的第一帧被视为图像,并允许用户在图像上绘制矩形,在绘制矩形后,用户必须右键单击图像以确认矩形。 当鼠标右键单击时,图像消失,video开始播放,其上绘制的矩形。

我能够完美地绘制矩形,但我无法将该矩形设置为ROI。

我想要做的是将该矩形设置为感兴趣区域(ROI),以对该ROI进行一些图像处理。 我无法将我绘制的矩形设置为ROI。

我在Visual Studio 2010中使用OpenCV。稍后我将尝试将此程序集成到QT创建器中。

任何帮助,将不胜感激。

提前致谢。

我的完整代码如下:

#include  #include  #include  #include  #include #include  #include  #include  #include  using namespace cv; using namespace std; void my_mouse_callback( int event, int x, int y, int flags, void* param ); bool destroy=false; CvRect box; IplImage* image; IplImage* frame2; bool drawing_box = false; void draw_box( IplImage* img, CvRect rect) { cvRectangle( img, cvPoint(box.x, box.y), cvPoint(box.x+box.width,box.y+box.height), cvScalar(0,0,255) ,2); CvRect rect2=cvRect(box.x,box.y,box.width,box.height); //cvSetImageROI(image, rect2); //here I wanted to set the drawn rect as ROI } // Implement mouse callback void my_mouse_callback( int event, int x, int y, int flags, void* param ){ IplImage* image = (IplImage*) param; switch( event ){ case CV_EVENT_MOUSEMOVE: if( drawing_box ) { box.width = x-box.x; box.height = y-box.y; } break; case CV_EVENT_LBUTTONDOWN: drawing_box = true; box = cvRect( x, y, 0, 0 ); break; case CV_EVENT_LBUTTONUP: drawing_box = false; if( box.width < 0 ) { box.x += box.width; box.width *= -1; } if( box.height depth,temp->nChannels); //cvNot(temp,temp); /* copy subimage */ //cvCopy(temp, temp, NULL); // Main loop while( 1 ) { if(destroy) {cvDestroyWindow(name); break;} cvCopyImage( image, temp ); if( drawing_box ) draw_box( temp, box ); cvMoveWindow(name, 200, 100); cvShowImage( name, temp ); if( cvWaitKey( 15 )==27 ) break; } //cvReleaseImage( &image ); cvReleaseImage( &temp ); cvDestroyWindow( name ); cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE ); cvMoveWindow("Example2", 150, 150); while(1) { frame2 = cvQueryFrame( capture ); draw_box(frame2,box); if( !frame2 ) break; cvShowImage( "Example2", frame2 ); char c = cvWaitKey(33); if( c == 27 ) break; } cvReleaseCapture( &capture ); cvDestroyWindow( "Example2" ); return 0; } 

你快到了。 但是有一个问题: case CV_EVENT_RBUTTONUP需要break ,我还会在default情况下添加一个break

以下代码设置ROI,对其执行简单的灰度处理,然后将处理后的ROI复制回原始图像。

出于测试目的,我将代码更改为使用相机而不是加载文件。

输出

在此处输入图像描述

代码

 #include  #include  #include  #include  #include  #include  using namespace cv; using namespace std; void my_mouse_callback( int event, int x, int y, int flags, void* param ); bool destroy=false; CvRect box; bool drawing_box = false; void draw_box(IplImage* img, CvRect rect) { cvRectangle(img, cvPoint(box.x, box.y), cvPoint(box.x+box.width,box.y+box.height), cvScalar(0,0,255) ,2); CvRect rect2=cvRect(box.x,box.y,box.width,box.height); //cvSetImageROI(image, rect2); //here I wanted to set the drawn rect as ROI } // Implement mouse callback void my_mouse_callback( int event, int x, int y, int flags, void* param ) { IplImage* frame = (IplImage*) param; switch( event ) { case CV_EVENT_MOUSEMOVE: { if( drawing_box ) { box.width = x-box.x; box.height = y-box.y; } } break; case CV_EVENT_LBUTTONDOWN: { drawing_box = true; box = cvRect( x, y, 0, 0 ); } break; case CV_EVENT_LBUTTONUP: { drawing_box = false; if( box.width < 0 ) { box.x += box.width; box.width *= -1; } if( box.height < 0 ) { box.y += box.height; box.height *= -1; } draw_box(frame, box); } break; case CV_EVENT_RBUTTONUP: { destroy=true; } break; default: break; } } int main() { const char* name = "Box Example"; cvNamedWindow( name ); box = cvRect(0,0,1,1); CvCapture* capture = cvCaptureFromCAM(0); if (!capture) { printf("!!! Failed cvCaptureFromCAM\n"); return 1; } IplImage* image = cvQueryFrame(capture); if (!image) { printf("!!! Failed cvQueryFrame #1\n"); return 2; } IplImage* temp = cvCloneImage(image); // Set up the callback cvSetMouseCallback(name, my_mouse_callback, (void*) image); // Main loop while( 1 ) { if (destroy) { cvDestroyWindow(name); break; } cvCopyImage(image, temp); if (drawing_box) draw_box(temp, box); cvMoveWindow(name, 200, 100); cvShowImage(name, temp); if (cvWaitKey(15) == 27) break; } cvReleaseImage(&temp); cvDestroyWindow(name); cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE); cvMoveWindow("Example2", 150, 150); // Retrieve a single frame from the device and set the ROI IplImage* vid_frame = cvQueryFrame(capture); if (!vid_frame) { printf("!!! Failed cvQueryFrame #2\n"); return 2; } cvSetImageROI(vid_frame, box); // Allocate space for a single-channel ROI (to store grayscale frames) IplImage* gray_roi = cvCreateImage(cvSize(box.width, box.height), IPL_DEPTH_8U, 1); IplImage* rgb_roi = cvCreateImage(cvSize(box.width, box.height), IPL_DEPTH_8U, 3); while(1) { if (!vid_frame) { vid_frame = cvQueryFrame(capture); if (!vid_frame) { printf("!!! Failed cvQueryFrame #3\n"); break; } } draw_box(vid_frame, box); // Set ROI and perform some processing (in this case, converting the ROI to grayscale) cvSetImageROI(vid_frame, box); cvCvtColor(vid_frame, gray_roi, CV_BGR2GRAY); //cvShowImage("Example2", gray_roi); /* At this point gray_roi has the size of thei ROI and contains the processed image. * For fun, we copy the processed image back to the original image and display it on the screen! */ cvCvtColor(gray_roi, rgb_roi, CV_GRAY2BGR); // As the ROI is still set, cvCopy is affected by it cvCopy(rgb_roi, vid_frame, NULL); // Now reset the ROI so cvShowImage displays the full image cvResetImageROI(vid_frame); cvShowImage("Example2", vid_frame); char c = cvWaitKey(33); if( c == 27 ) break; vid_frame = NULL; } cvSaveImage("processed.jpg", vid_frame); cvReleaseImage(&gray_roi); cvReleaseImage(&rgb_roi); cvReleaseCapture( &capture ); cvDestroyWindow( "Example2" ); return 0; }