OpenCV来控制鼠标移动

来源:互联网 发布:2017淘宝生意好差 编辑:程序博客网 时间:2024/05/17 03:36

之前的日志“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//基本的图像指针
007IplImage *image = 0
008, *hsv = 0
009, *hue = 0
010, *mask = 0
011, *backproject = 0
012, *histimg = 0;
013 
014//用于直方图
015CvHistogram *hist = 0;
016 
017//用于判断
018int select_object = 0;
019int track_object = 0;
020int cursor_object=0;
021 
022//用于鼠标选择区域
023CvPoint origin;
024CvRect selection;
025 
026//CAMSHIFT算法用到
027CvRect track_window;
028CvBox2D track_box;
029CvConnectedComp track_comp;
030 
031// 划分HIST的个数,越高越精确
032int hdims = 48;   
033 
034//设置HSV的范围(0-180)
035float hranges_arr[] = {0,180};
036float* hranges = hranges_arr;
037 
038void 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。
085CvScalar 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 
108int 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

原创粉丝点击