zoukankan      html  css  js  c++  java
  • Opencv函数setMouseCallback鼠标事件响应

    用户通过鼠标对图像视窗最常见的操作有:

    1. 左键单击按下

    2. 左键单击抬起

    3. 左键按下拖动

    4. 鼠标指针位置移动


    单次单击操作响应事件及顺序

    Opencv中setMouseCallback()创建了一个鼠标回调函数,每次在图像上单击鼠标左键再抬起的过程,都会分3次调用鼠标响应函数,并且响应顺序是:

    1.左键单击按下;

    2.左键单击抬起;

    3.鼠标指针位置移动(即使原地单击,鼠标位置并没有移动);


    可以编码验证一下回调函数的这个调用机制:

    #include "core/core.hpp"
    #include "highgui/highgui.hpp"
    #include "imgproc/imgproc.hpp"
    #include<iostream>
    
    using namespace cv;
    using namespace std;
    
    void OnMouseAction(int event,int x,int y,int flags,void *ustc);  //鼠标回调事件函数
    int static times; //记录调用次数
    
    
    int main(int argc,char*argv[])
    {
    	Mat image=imread(argv[1]);
    	imshow("image",image);
    	setMouseCallback("image",OnMouseAction);
    	waitKey();
    	system("pause");
    }
    
    //*******************************************************************//
    //鼠标回调函数
    
    void OnMouseAction(int event,int x,int y,int flags,void *ustc)
    {	
    	times++;
    	cout<<"第 "<<times<<" 次回调鼠标事件"<<endl;
    	if(event==CV_EVENT_MOUSEMOVE)
    	{
    		cout<<"触发鼠标移动事件"<<endl;
    	}
    	if(event==CV_EVENT_LBUTTONDOWN)
    	{
    		cout<<"触发左键按下事件"<<endl;
    	}
    	if(event==CV_EVENT_LBUTTONUP)
    	{
    		cout<<"触发左键抬起事件"<<endl;
    	}
    	if(event==CV_EVENT_RBUTTONDOWN)
    	{
    		cout<<"触发右键按下事件"<<endl;
    	}
    	if(event==CV_EVENT_RBUTTONUP)
    	{
    		cout<<"触发右键抬起事件"<<endl;
    	}
    	if(event==CV_EVENT_LBUTTONDBLCLK)
    	{
    		cout<<"触发左键双击事件"<<endl;
    	}
    	if(event==CV_EVENT_RBUTTONDBLCLK)
    	{
    		cout<<"触发右键双击事件"<<endl;
    	}
    }
    



    前3次调用是在左键单击前鼠标指针在图像窗口移动造成的。不移动位置,单击左键,触发了第4次调用,红色框框内的就是一个完整的鼠标按下再抬起的调用过程:

    第一次传入的event事件是左键单击“CV_EVENT_LBUTTONDOWN”;

    第二次传入的event事件是左键抬起“CV_EVENT_LBUTTONUP”;

    第三次传入的event事件是鼠标移动“CV_EVENT_MOUSEMOVE”,这时候鼠标物理位置其实并没有移动;


    setMouseCallback()函数

    了解了鼠标回调函数的调用机制后再来看一下创建回调函数的函数setMouseCallback();

    原型:

    void setMouseCallback(const string& winname,     //图像视窗名称
    MouseCallback onMouse,     //鼠标响应函数,监视到鼠标操作后调用并处理相应动作
    void* userdata = 0        //鼠标响应处理函数的ID,识别号
    );


    OnMouseAction()响应函数

    鼠标事件回调函数onMouse按照固定格式创建响应函数:

    void OnMouseAction(int event,int x,int y,int flags,void *ustc) 


    event事件代表了鼠标的各种操作,详细看一下各个event事件:

    Event:
    #define CV_EVENT_MOUSEMOVE 0             //滑动
    #define CV_EVENT_LBUTTONDOWN 1           //左键点击
    #define CV_EVENT_RBUTTONDOWN 2           //右键点击
    #define CV_EVENT_MBUTTONDOWN 3           //中键点击
    #define CV_EVENT_LBUTTONUP 4             //左键放开
    #define CV_EVENT_RBUTTONUP 5             //右键放开
    #define CV_EVENT_MBUTTONUP 6             //中键放开
    #define CV_EVENT_LBUTTONDBLCLK 7         //左键双击
    #define CV_EVENT_RBUTTONDBLCLK 8         //右键双击
    #define CV_EVENT_MBUTTONDBLCLK 9         //中键双击


    int x,int y,代表鼠标位于窗口的(x,y)坐标位置,即Point(x,y);

    int flags,代表鼠标的拖拽事件,以及键盘鼠标联合事件,共有32种事件:

    flags:
    #define CV_EVENT_FLAG_LBUTTON 1       //左鍵拖曳
    #define CV_EVENT_FLAG_RBUTTON 2       //右鍵拖曳
    #define CV_EVENT_FLAG_MBUTTON 4       //中鍵拖曳
    #define CV_EVENT_FLAG_CTRLKEY 8       //(8~15)按Ctrl不放事件
    #define CV_EVENT_FLAG_SHIFTKEY 16     //(16~31)按Shift不放事件
    #define CV_EVENT_FLAG_ALTKEY 32       //(32~39)按Alt不放事件


    函数指针 void *ustc标识了所响应的事件函数,相当于自定义了一个OnMouseAction()函数的ID。

    简单应用:记录鼠标按下时坐标和鼠标抬起时坐标,分别做Line、Rectangle、Circle


    #include "core/core.hpp"
    #include "highgui/highgui.hpp"
    #include "imgproc/imgproc.hpp"
    #include<iostream>
    
    using namespace cv;
    using namespace std;
    
    void OnMouseAction(int event,int x,int y,int flags,void *ustc);  //鼠标回调事件函数
    int static times; //记录调用次数
    
    int rowsBegin,rowsEnd;
    int colsBegin,colsEnd;
    Mat image;
    
    int main(int argc,char*argv[])
    {
    	image=imread(argv[1]);
    	imshow("image",image);
    	setMouseCallback("image",OnMouseAction);	
    }
    
    //*******************************************************************//
    //鼠标回调函数
    void OnMouseAction(int event,int x,int y,int flags,void *ustc)
    {	
    	if(event==CV_EVENT_MOUSEMOVE)
    	{
    		cout<<"触发鼠标移动事件"<<endl;
    	}
    	if(event==CV_EVENT_LBUTTONDOWN)
    	{
    		rowsBegin=y;
    		colsBegin=x;
    		cout<<"触发左键按下事件"<<endl;
    	}
    	if(event==CV_EVENT_LBUTTONUP)
    	{
    		rowsEnd=y;
    		colsEnd=x;
    		line(image,Point(colsBegin,rowsBegin),Point(colsEnd,rowsEnd),Scalar(255,0,0),2,8,0);
    		rectangle(image,Rect(colsBegin,rowsBegin,colsEnd-colsBegin,rowsEnd-rowsBegin),Scalar(0,255,0),2,8,0);
    		circle(image,Point((colsEnd+colsBegin)/2,(rowsEnd+rowsBegin)/2),rowsEnd-rowsBegin,Scalar(0,0,255),2,8,0);
    		imshow("image",image);
    		cout<<"触发左键抬起事件"<<endl;
    	}
    	if(event==CV_EVENT_RBUTTONDOWN)
    	{
    		cout<<"触发右键按下事件"<<endl;
    	}
    	if(event==CV_EVENT_RBUTTONUP)
    	{
    		cout<<"触发右键抬起事件"<<endl;
    	}
    	if(event==CV_EVENT_LBUTTONDBLCLK)
    	{
    		cout<<"触发左键双击事件"<<endl;
    	}
    	if(event==CV_EVENT_RBUTTONDBLCLK)
    	{
    		cout<<"触发右键双击事件"<<endl;
    	}
    }
    

    左键单击按下之后拖动鼠标到某一个位置之后松开:












  • 相关阅读:
    Apache OFBiz 学习笔记 之 实体引擎
    Apache OFBiz 学习笔记 之 服务引擎 二
    Apache OFBiz 学习笔记 之 服务引擎 一
    [OFBiz]开发 五
    [OFBiz]开发 四
    [OFBiz]开发 三
    [OFBiz]开发 二
    通过Wmi实现Hyper-V远程管理(一)
    wifi智能插座 一键扫描局域网内插座Ip及其它信息 Python源代码API
    .NET4.0下使用Net2.0类库或程序集
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9412000.html
Copyright © 2011-2022 走看看