CV编程常用的获取鼠标圈定区域的方法

  在CV里面,很多时候需要自己手动截出一块区域,然后针对这块区域进行处理,OpenCV并没有提供直接可调用的函数,如果每次都要自己写的话,估计写获取鼠标圈定区域就需要花很有一段时间~

  近来是在做视频跟踪这一块,有的跟踪是基于检测的跟踪,则不需要手动圈定,但很多时候,为了能直接看到跟踪的效果,则采取手动圈定的方式,如下图所示:

  我在看粒子滤波源码的时候发现了其鼠标圈定函数写的已经比较好调用,后来再看到meanshift跟踪,发现所用获取鼠标圈定函数一样的,所以我将其收集下来,以备后用,唔,接下来就是贴代码,这上面有部分我自己的代码……

  若能看懂其鼠标圈定函数,则对自己以后写此函数很有裨益,注释就不写那么多了,整体也比较容易吧:

  1 #include <cv.h>
  2 #include <highgui.h>
  3 
//-------------- 控制获取区域个数 4 const int MAX_OBJECTS = 1; 5
  //-------- 对参数封装 cvSetMouseCallback 所需参数
  6 typedef struct params {
  7   CvPoint loc1[MAX_OBJECTS];
  8   CvPoint loc2[MAX_OBJECTS];
  9   IplImage* objects[MAX_OBJECTS];
 10   char* win_name;
 11   IplImage* orig_img;
 12   IplImage* cur_img;
 13   int n;
 14 } params;
 15 
 16 int GetRegions( IplImage*, CvRect** );
 17 void mouse( int, int, int, int, void* );
 18 
 19 int main(void)
 20 {
 21     IplImage *frame, *frame_copy;
 22     CvCapture *video;
 23     CvScalar color;
 24     CvRect* regions;
 25 
 26     char *video_file = "E:\\Coding\\acivs\\1.AVI";
 27 
 28     video = cvCaptureFromFile( video_file );
 29     if(!video)
 30     {
 31         printf("Cannot open the video file!!!");
 32         return -1;
 33     }
 34 
 35     int frmNo = 0, nObjects = 0;
 36     while( frame = cvQueryFrame( video ) )
 37     {
 38         frame_copy = cvCloneImage( frame );
 39         if(frmNo == 0)
 40         {
 41             printf("Please select a region to track !");
 42             while( nObjects == 0 )
 43             {
 44                 nObjects = GetRegions( frame, &regions );
 45                 if( nObjects == 0 )
 46                     printf( "Please select a object\n" );
 47             }
 48         }
 49         else
 50         {
 51             printf("This is the %d st frame\n", frmNo);
 52 
 53         }
 54         frmNo++;
 55         cvReleaseImage(&frame_copy);
 56     }
 57 
 58     cvReleaseCapture( &video );
 59     return 0;
 60 }
 61 //-------- 获取的区域 regions
 62 int GetRegions( IplImage* frame, CvRect** regions )
 63 {
 64   char* win_name = "First frame";
 65   params p;
 66   CvRect* r;
 67   int i, x1, y1, x2, y2, w, h;
 68   
 69   /* use mouse callback to allow user to define object regions */
 70   p.win_name = win_name;
 71   p.orig_img = cvCloneImage( frame );
 72   p.cur_img = NULL;
 73   p.n = 0;
 74   cvNamedWindow( win_name, 1 );
 75   cvShowImage( win_name, frame );
 76   cvSetMouseCallback( win_name, &mouse, &p );
 77   cvWaitKey( 0 );
 78   cvDestroyWindow( win_name );
 79   cvReleaseImage( &(p.orig_img) );
 80   if( p.cur_img )
 81     cvReleaseImage( &(p.cur_img) );
 82 
 83   /* extract regions defined by user; store as an array of rectangles */
 84   if( p.n == 0 )
 85     {
 86       *regions = NULL;
 87       return 0;
 88     }
 89   r = (CvRect *)malloc( p.n * sizeof( CvRect ) );
 90   for( i = 0; i < p.n; i++ )
 91     {
 92       x1 = MIN( p.loc1[i].x, p.loc2[i].x );
 93       x2 = MAX( p.loc1[i].x, p.loc2[i].x );
 94       y1 = MIN( p.loc1[i].y, p.loc2[i].y );
 95       y2 = MAX( p.loc1[i].y, p.loc2[i].y );
 96       w = x2 - x1;
 97       h = y2 - y1;
 98 
 99       /* ensure odd width and height */
100       w = ( w % 2 )? w : w+1;
101       h = ( h % 2 )? h : h+1;
102       r[i] = cvRect( x1, y1, w, h );
103     }
104   *regions = r;
105   return p.n;
106 }
107 
108 void mouse( int event, int x, int y, int flags, void* param )
109 {
110   params* p = (params*)param;
111   CvPoint* loc;
112   int n;
113   IplImage* tmp;
114   static int pressed = FALSE;
115   
116   /* on left button press, remember first corner of rectangle around object */
117   if( event == CV_EVENT_LBUTTONDOWN )
118     {
119       n = p->n;
120       if( n == MAX_OBJECTS )
121     return;
122       loc = p->loc1;
123       loc[n].x = x;
124       loc[n].y = y;
125       pressed = TRUE;
126     }
127 
128   /* on left button up, finalize the rectangle and draw it in black */
129   else if( event == CV_EVENT_LBUTTONUP )
130     {
131       n = p->n;
132       if( n == MAX_OBJECTS )
133     return;
134       loc = p->loc2;
135       loc[n].x = x;
136       loc[n].y = y;
137       cvReleaseImage( &(p->cur_img) );
138       p->cur_img = NULL;
139       cvRectangle( p->orig_img, p->loc1[n], loc[n], CV_RGB(0,0,0), 1, 8, 0 );
140       cvShowImage( p->win_name, p->orig_img );
141       pressed = FALSE;
142       p->n++;
143     }
144 
145   /* on mouse move with left button down, draw rectangle as defined in white */
146   else if( event == CV_EVENT_MOUSEMOVE  &&  flags & CV_EVENT_FLAG_LBUTTON )
147     {
148       n = p->n;
149       if( n == MAX_OBJECTS )
150     return;
151       tmp = cvCloneImage( p->orig_img );
152       loc = p->loc1;
153       cvRectangle( tmp, loc[n], cvPoint(x, y), CV_RGB(255,255,255), 1, 8, 0 );
154       cvShowImage( p->win_name, tmp );
155       if( p->cur_img )
156     cvReleaseImage( &(p->cur_img) );
157       p->cur_img = tmp;
158     }
159 }
原文地址:https://www.cnblogs.com/moondark/p/2582013.html