OpenCV来控制鼠标移动

之前的日志“VS2005下配置OpenCV2.1 ” 里介绍了如何在VS2005里安装OpenCV2.1,下面这篇日志里就介绍了下如何使用CV来控制鼠标移动。代码和AutoCamShift例子里的差 不多,只是我进行了许多代码的删减以及我添加稍许注释,另外就是补充了::SetCursorPos(_x,_y)函数。

不太多说废话,C++代码如下:

view source
print ?
001 #include "cv.h"
002 #include "highgui.h"
003 #include
004 #include
005  
006 //基本的图像指针
007 IplImage *image = 0
008 , *hsv = 0
009 , *hue = 0
010 , *mask = 0
011 , *backproject = 0
012 , *histimg = 0;
013  
014 //用于直方图
015 CvHistogram *hist = 0;
016  
017 //用于判断
018 int select_object = 0;
019 int track_object = 0;
020 int cursor_object=0;
021  
022 //用于鼠标选择区域
023 CvPoint origin;
024 CvRect selection;
025  
026 //CAMSHIFT算法用到
027 CvRect track_window;
028 CvBox2D track_box;
029 CvConnectedComp track_comp;
030  
031 // 划分HIST的个数,越高越精确
032 int hdims = 48;   
033  
034 //设置HSV的范围(0-180)
035 float hranges_arr[] = {0,180};
036 float * hranges = hranges_arr;
037  
038 void on_mouse( int event, int x, int y, int flags, void * param)
039 {
040      if ( !image )
041          return ;
042  
043      if ( image->origin )
044          y = image->height - y;
045  
046      //左键按下时 select_object=1
047      //右键按下时 select_object=0
048      if ( select_object )
049      {
050          selection.x = MIN(x,origin.x);
051          selection.y = MIN(y,origin.y);
052          selection.width = selection.x + CV_IABS(x - origin.x);
053          selection.height = selection.y + CV_IABS(y - origin.y);
054  
055          selection.x = MAX( selection.x, 0 );
056          selection.y = MAX( selection.y, 0 );
057          selection.width = MIN( selection.width, image->width );
058          selection.height = MIN( selection.height, image->height );
059          selection.width  -= selection.x;
060          selection.height -= selection.y;
061  
062      }
063  
064      switch ( event )
065      {
066      case CV_EVENT_LBUTTONDOWN:
067          origin = cvPoint(x,y);
068          selection = cvRect(x,y,0,0);
069          select_object = 1;
070          break ;
071      case CV_EVENT_LBUTTONUP:
072          select_object = 0;
073          if ( selection.width > 0 && selection.height > 0 )
074              track_object = -1;
075 #ifdef _DEBUG
076          printf ( "/n # 鼠标的选择区域:" );
077          printf ( "/n   X = %d, Y = %d, Width = %d, Height = %d" ,
078              selection.x, selection.y, selection.width, selection.height);
079 #endif
080          break ;
081      }
082 }
083  
084 //画直方图里用到。HSV---->RGB,返回cvScalar。
085 CvScalar hsv2rgb( float hue )
086 {
087      int rgb[3], p, sector;
088      static const int sector_data[][3]=
089      {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
090      hue *= 0.033333333333333333333333333333333f;
091      sector = cvFloor(hue);
092      p = cvRound(255*(hue - sector));
093      p ^= sector & 1 ? 255 : 0;
094  
095      rgb[sector_data[sector][0]] = 255;
096      rgb[sector_data[sector][1]] = 0;
097      rgb[sector_data[sector][2]] = p;
098  
099 #ifdef _DEBUG
100      printf ( "/n # Convert HSV to RGB:" );
101      printf ( "/n   HUE = %f" , hue);
102      printf ( "/n   R = %d, G = %d, B = %d" , rgb[0],rgb[1],rgb[2]);
103 #endif
104  
105      return cvScalar(rgb[2], rgb[1], rgb[0],0);
106 }
107  
108 int main( int argc, char ** argv )
109 {
110      CvCapture* capture = 0;
111      IplImage* frame = 0;
112  
113      capture = cvCaptureFromCAM(0);
114  
115      int frameH    = ( int ) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
116      int frameW    = ( int ) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
117  
118      if ( !capture )
119      {
120          fprintf (stderr, "Could not initialize capturing.../n" );
121          return -1;
122      }
123  
124      cvNamedWindow( "CamShiftDemo" , 1 );
125      cvSetMouseCallback( "CamShiftDemo" , on_mouse, NULL );
126  
127      for (;;)
128      {
129          int bin_w,ori_x,i,c;       
130  
131          ori_x=selection.x+(selection.width/2);
132  
133          frame = cvQueryFrame( capture );
134          if ( !frame )
135              break ;
136  
137          if ( !image )
138          {
139              image = cvCreateImage( cvGetSize(frame), 8, 3 );
140              image->origin = frame->origin;
141  
142              hsv               = cvCreateImage( cvGetSize(frame), 8, 3 );
143              hue               = cvCreateImage( cvGetSize(frame), 8, 1 );
144              mask            = cvCreateImage( cvGetSize(frame), 8, 1 );
145              backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
146              histimg         = cvCreateImage( cvSize(320,200), 8, 3 );
147              cvZero( histimg );
148  
149              hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );  // 计算直方图
150  
151          }
152  
153          cvCopy(frame, image, 0 );
154          cvCvtColor( image, hsv, CV_BGR2HSV );  // 彩色空间转换 BGR to HSV
155  
156          if ( track_object )
157          {
158              int _vmin = 10;
159              int _vmax = 256;
160  
161              cvInRangeS( hsv,
162                  cvScalar(0,30,MIN(_vmin,_vmax),0),
163                  cvScalar(180,256,MAX(_vmin,_vmax),0),
164                  mask );  // 得到二值的MASK
165  
166              cvSplit( hsv, hue, 0, 0, 0 );  // 只提取 HUE 分量
167  
168              if ( track_object < 0 )
169              {
170                  float max_val = 0.f;
171                  cvSetImageROI( hue, selection );  // 得到选择区域 for ROI
172                  cvSetImageROI( mask, selection ); // 得到选择区域 for mask
173                  cvCalcHist( &hue, hist, 0, mask ); // 计算直方图
174                  cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );  // 只找最大值
175                  cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); // 缩放 bin 到区间 [0,255]
176                  cvResetImageROI( hue );  // remove ROI
177                  cvResetImageROI( mask );
178                  track_window = selection;
179                  track_object = 1;
180  
181                  cvZero( histimg );
182  
183                  bin_w= histimg->width / hdims;  // hdims: 条的个数,则 bin_w 为条的宽度
184  
185                  // 画直方图
186                  for (i = 0; i < hdims; ++i)
187                  {
188                      int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); //cvRound一种舍入的方法把浮点数转为整形
189  
190                      CvScalar color = hsv2rgb(i*180.f/hdims);
191                      cvRectangle(histimg,
192                          cvPoint(i*bin_w,histimg->height), //矩形左下角
193                          cvPoint((i+1)*bin_w,histimg->height - val), //矩形右上角
194                          color,
195                          -1,
196                          8,
197                          0 );
198                  }
199              }
200  
201              // 使用back project方法计算hue的反向投影
202              cvCalcBackProject( &hue, backproject, hist ); 
203  
204              cvAnd( backproject, mask, backproject, 0 );
205  
206              // CAMSHIFT算法
207              cvCamShift( backproject,  //目标直方图的反向投影
208                  track_window, //初始搜索窗口
209                  cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ), //窗口搜索停止的准则
210                  &track_comp, //象素点的和
211                  &track_box );
212  
213              //改变光标
214              if (cursor_object)
215              {
216                  int _x=track_box.center.x/frameW*1280;
217                  int _y=track_box.center.y/frameH*800;
218                  ::SetCursorPos(_x,_y);
219              }
220  
221              //新旧交替
222              track_window = track_comp.rect;
223  
224              if ( image->origin )
225                  track_box.angle = -track_box.angle;
226  
227              //绘制椭圆
228              cvEllipseBox(image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
229  
230          }
231  
232          if ( select_object && selection.width > 0 && selection.height > 0)
233          {
234              cvSetImageROI( image, selection ); //基于给定的值设置感兴趣通道
235              cvXorS( image, cvScalarAll(255), image, 0 ); //计算数组元素与数量之间的按位异或
236              cvResetImageROI( image ); //释放图像的ROI
237          }
238  
239          cvShowImage( "CamShiftDemo" , image );
240          cvShowImage( "Histogram" , histimg );
241  
242          c=cvWaitKey(10);
243          if ( ( char ) c == 27 )
244              break ;
245          switch ( ( char ) c )
246          {
247          case 'm' :
248              if (cursor_object)
249                  cursor_object=0;
250              else
251                 cursor_object=1;
252              break ;
253          default :
254              ;
255          }
256  
257      }
258  
259      cvReleaseCapture( &capture );
260      cvDestroyWindow( "CamShiftDemo" );
261  
262      return 0;
263 }

整个代码里只控制了鼠标的移动,可是如何模仿鼠标的单击和双击以及右键呢?~如果你有思路希望你可以告诉我,共同探讨一下。


超越C++ 原创文章,转载请注明来源并保留原文链接

本文链接:http://www.beyondc.cn/opencv-to-control-the-mouse.html

你可能感兴趣的:(C/C++)