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

文章目录

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

1、鼠标事件函数:
(1)鼠标事件函数原型:setMouseCallback(),此函数会在调用之后不断查询回调函数onMouse(),直到窗口销毁
cpp 复制代码
  void setMouseCallback(
	const String& winname, 
	MouseCallback onMouse, 
	void* userdata = 0
)

参数解释:
 winname:窗口名称;
 onMouse:回调函数;
 userdata:传递给回调函数用户自定义的外部数据,userdata是一个 void 类型的指针;
(2)回调函数onMouse(),可随意命名,但是要与 setMouseCallback()函数里的回调函数名称一致
cpp 复制代码
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 类型的指针;
2、代码示例:

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

(1)main.cpp
cpp 复制代码
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>

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;
}
(2)头文件demo.h
cpp 复制代码
#include <opencv2/opencv.hpp>

using namespace cv;

class Demo
{
public:
	void mouseEvent(Mat &image);
private:

};
(3)demo.cpp
cpp 复制代码
#include <Demo.h>

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();
}
(4)效果演示
相关推荐
张子夜 iiii6 小时前
实战项目-----Python+OpenCV 实现对视频的椒盐噪声注入与实时平滑还原”
开发语言·python·opencv·计算机视觉
小王爱学人工智能7 小时前
OpenCV的图像金字塔
人工智能·opencv·计算机视觉
@areok@8 小时前
C++mat传入C#OpencvCSharp的mat
开发语言·c++·opencv·c#
WeiJingYu.14 小时前
O3.1 opencv高阶
人工智能·opencv·计算机视觉
Monkey的自我迭代16 小时前
图像金字塔---图像上采样下采样
人工智能·opencv·计算机视觉
dlraba80218 小时前
OpenCV 实战:多角度模板匹配实现图像目标精准定位
人工智能·opencv·计算机视觉
人生游戏牛马NPC1号20 小时前
学习 Android (二十一) 学习 OpenCV (六)
android·opencv·学习
赴33520 小时前
opencv 银行卡号识别案例
人工智能·opencv·计算机视觉·银行卡号识别
鹅毛在路上了1 天前
C++, ffmpeg, libavcodec-RTSP拉流,opencv实时预览
c++·opencv·ffmpeg
Monkey的自我迭代1 天前
多目标轮廓匹配
人工智能·opencv·计算机视觉