使用鼠标从视频上的矩形设置 ROI
我有视频,当程序运行时,视频的第一帧作为图像,允许用户在图像上绘制矩形,绘制矩形后,用户必须右键单击图像进行确认矩形.当鼠标右键单击时,图像消失,视频开始播放,并在其上绘制矩形.
I have video, when the program is run the video's first frame is taken as an image and the user is allowed to draw a rectangle on the image, after the rectangle is drawn, the user must right click on the image to confirm the rectangle. When the mouse the right-clicked the image disappears and the video starts to play with the drawn rectangle on it.
我能够完美地绘制矩形,但我无法将该矩形设置为 ROI.
I am able to draw the rectangle perfectly but I can't set that rectangle as ROI.
我想要做的是将该矩形设置为感兴趣区域 (ROI),以便对该 ROI 进行一些图像处理.我无法将我绘制的矩形设置为 ROI.
What I want to do is to set that rectangle as Region of Interest (ROI) to do some image processing on that ROI. I am unable to set the rectangle which I draw as ROI.
我正在使用 OpenCV 和 Visual Studio 2010.稍后我将尝试将此程序集成到 QT Creator 中.
I am using OpenCV with Visual Studio 2010. Later on I will try to integrate this program in QT creator.
任何帮助将不胜感激.
提前致谢.
我的完整代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include<opencv2opencv.hpp>
#include <opencv2highguihighgui.hpp>
#include <opencv/highgui.h>
#include <opencv/cxcore.h>
#include <opencvcvaux.h>
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 < 0 )
{
box.y += box.height;
box.height *= -1;
}
draw_box( image, box);
break;
case CV_EVENT_RBUTTONUP:
destroy=true;
}
}
int main()
{
const char* name = "Box Example";
cvNamedWindow( name );
box = cvRect(0,0,1,1);
CvCapture* capture = cvCreateFileCapture( "C:\video.mp4" );
image = cvQueryFrame( capture );
IplImage* temp = cvCloneImage( image );
// Set up the callback
cvSetMouseCallback( name, my_mouse_callback, (void*) image);
//IplImage *img2 = cvCreateImage(cvGetSize(temp),temp->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
case 上添加一个 break
.
You were almost there. One problem though: case CV_EVENT_RBUTTONUP
needs to break
, and I would also add a break
on default
case.
以下代码设置 ROI,对其进行简单的灰度处理,然后将处理后的 ROI 复制回原始图像.
The following code sets the ROI, performs a simple grayscale processing on it and then copies the processed ROI back to the original image.
出于测试目的,我将您的代码更改为使用我的相机而不是加载文件.
For testing purposes I changed your code to use my camera instead of loading a file.
输出:
代码:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <cv.h>
#include <highgui.h>
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
");
return 1;
}
IplImage* image = cvQueryFrame(capture);
if (!image)
{
printf("!!! Failed cvQueryFrame #1
");
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
");
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
");
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;
}
相关文章