• opencv鼠标事件函数setMouseCallback()详解


    opencv鼠标事件函数setMouseCallback()详解
    1、鼠标事件函数:
    (1)鼠标事件函数原型:setMouseCallback(),此函数会在调用之后不断查询回调函数onMouse(),直到窗口销毁
      void setMouseCallback(
    	const String& winname, 
    	MouseCallback onMouse, 
    	void* userdata = 0
    )
    
    参数解释:
     winname:窗口名称;
     onMouse:回调函数;
     userdata:传递给回调函数用户自定义的外部数据,userdata是一个 void 类型的指针;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    (2)回调函数onMouse(),可随意命名,但是要与 setMouseCallback()函数里的回调函数名称一致
    void onMouse(
    	int event, 
    	int x, 
    	int y, 
    	int flags, 
    	void *userdata
    ) 
    
    参数解释:
    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         //中键双击
    );
    x和y:鼠标指针在图像坐标系的坐标;
    flags:鼠标事件标志的常量;
    userdata:回调函数接收,用户自定义的外部数据,userdata是一个 void 类型的指针;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    2、代码示例:

    利用鼠标事件函数,提取ROI区域:

    (1)main.cpp
    #include 
    #include 
    #include 
    
    using namespace cv;
    using namespace std;
    
    int main() {
    	//读取图像,BGR存储在Mat矩阵里
    	Mat src = cv::imread("C:\\cpp\\image\\suzy4.jpg");
    	if (src.empty()) {
    		printf("could not load image..../n");
    		return -1;
    	}
    
    	Demo demo;
    	demo.mouseEvent(src);
    
    	waitKey();
    	destroyAllWindows();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    (2)头文件demo.h
    #include 
    
    using namespace cv;
    
    class Demo
    {
    public:
    	void mouseEvent(Mat &image);
    private:
    
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    (3)demo.cpp
    #include 
    
    using namespace std;
    
    Point sp(-1, -1);
    Point ep(-1, -1);
    Mat temp;
    static void onMouse(int event, int x, int y, int flags, void *userdata) {
    	/**
    	* 对指针userdata,进行转换和解引用的操作,将userdata指向的Mat对象,赋值给名为image的变量,以便后续对图像数据的处理:
    	* userdata是一个void类型的指针,需要转换为Mat类型的指针,然后用*运算符解引用,得到Mat对象,再赋值给名为image的变量,这样就可以对image进行操作了;
    	*/
    	Mat image = *((Mat*)userdata);
    	if (event == EVENT_LBUTTONDOWN) {
    		// 起点坐标
    		sp.x = x;
    		sp.y = y;
    		std::cout << "start point:" << sp << std::endl;
    	}
    	else if (event == EVENT_LBUTTONUP) {
    		ep.x = x;
    		ep.y = y;
    		// 结束点坐标
    		int dx = ep.x - sp.x;
    		int dy = ep.y - sp.y;
    		if (dx > 0 && dy > 0) {
    			Rect box(sp.x, sp.y, dx, dy);
    			temp.copyTo(image);
    			imshow("ROI区域", image(box));
    			rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
    			imshow("鼠标绘制", image);
    			// ready for next drawing
    			sp.x = -1;
    			sp.y = -1;
    		}
    	}
    	else if (event == EVENT_MOUSEMOVE) {
    		if (sp.x > 0 && sp.y > 0) {
    			ep.x = x;
    			ep.y = y;
    			int dx = ep.x - sp.x;
    			int dy = ep.y - sp.y;
    			if (dx > 0 && dy > 0) {
    				Rect box(sp.x, sp.y, dx, dy);
    				temp.copyTo(image);
    				rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
    				imshow("鼠标绘制", image);
    			}
    		}
    	}
    }
    
    void Demo::mouseEvent(Mat &image) {
    	namedWindow("鼠标事件", WINDOW_AUTOSIZE);
    
    	/**
    	* 由于回调函数需要传入的是一个void类型指针,我们先取image的地址,再将&image强制转换为void类型指针,具体操作如下:
    	* &image:获取变量image的内存地址,即Mat对象的指针;
    	* (void*):是一个强制类型转换,将image的地址转换为void类型指针,这样就可以将参数传递给回调函数了;
    	*/
    	setMouseCallback("鼠标绘制", onMouse, (void*)(&image));
    	imshow("鼠标绘制", image);
    	temp = image.clone();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    (4)效果演示

    在这里插入图片描述

  • 相关阅读:
    一零一九、岗位数据分析(Spark)
    LSKA(大可分离核注意力):重新思考CNN大核注意力设计
    深入理解磁盘阵列(RAID)和逻辑卷管理(LVM)技术及应用指南
    私信功能的设计与实现
    【软考-中级】系统集成项目管理工程师-配置管理历年案例
    『Flutter』开篇
    【LabVIEW FPGA入门】NI 环境安装教程
    openresty lua-resty-lock数据库锁
    Kafka源码分析(四) - Server端-请求处理框架
    C++ 基础入门 之 注释 ( // 和 /**/ )/变量 /常量 ( #define 和 const )/关键字/标识符(变量名)命名规则
  • 原文地址:https://blog.csdn.net/qq_33867131/article/details/132583785