opencv c++ 鼠标操作与响应(17)

本文详细介绍了如何使用OpenCV在GUI窗口中实现鼠标点击事件的不同反馈,如左键点击框选、移动绘制椭圆,以及ROI区域的实时显示。通过实例展示了如何设置鼠标回调函数和关键控制变量,以实现实时图像处理和交互功能。
摘要由CSDN通过智能技术生成

目的:在点击不同的鼠标键时,能得到不同的反馈或菜单选项。

API

setMouseCallback(窗口名, 鼠标事件反馈静态函数, (void*)(&image));

注:userdata用于传输数据。

onMouse的定义格式:

opencv鼠标事件官网查询:

OpenCV: Flags related creating and manipulating HighGUI windows and mouse events

实例:根据鼠标左键点击和抬起实时框出图像,并反馈ROI窗口

1、定义全局变量来辅助控制

//定义全局变量来辅助记录鼠标状态
Point sp(-1, -1);
Point ep(-1, -1);
Mat temp;

sp——鼠标左键点击点,初始化为(-1,-1)

ep——鼠标左键松开点,初始化为(-1,-1)

temp——用于保存原图,在实时反馈框图时不被过多的框遮住原图(即在鼠标移动绘制过程中,将带框图像重置为原图,并绘制新框图)

2、鼠标事件反馈静态函数定义

这里需要定义鼠标左键被点击时、鼠标移动时,鼠标左键抬起时的事件。

2、1鼠标左键被点击时

更新起始点,反馈点击位置即可。

2、2鼠标左键抬起时

更新终止点,当框图是从左上往右下绘制时,绘制方框,并显示被方框框住的ROI区域,最后重置起始点。

2、3鼠标移动时

在满足鼠标左键点击的判定条件下,更新终止点(暂时的),当框图是从左上往右下绘制时,首先重置上一步移动时绘制的带方框原图(利用暂存的Mat temp来实现),并绘制这一步移动的方框。

static void on_draw(int event, int x, int y, int flag, void* userdata) {
	Mat image = *((Mat*)userdata);
	if (event == EVENT_LBUTTONDOWN) {
		sp.x = x;
		sp.y = y;
		cout << "start point :" << sp << 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);
			rectangle(image, box, Scalar(0, 255, 0), 2, 8, 0);
			imshow("鼠标绘制", image);
			imshow("ROI区域", image(box));
			//为下次绘制重置sp
			sp.x = -1;
			sp.y = -1;
		}
		
			
		cout << "end point :" << ep << endl;
	}
	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) {
				//为了使矩形不重复绘制,遮盖原图,每次都用克隆的临时原图来进行重置,消除上一步鼠标移动绘制出的矩形
				temp.copyTo(image);

				Rect box(sp.x, sp.y, dx, dy);
				rectangle(image, box, Scalar(0, 255, 0), 2, 8, 0);
				imshow("鼠标绘制", image);
			}
		}
	}
}

3、主体函数部分

void QuickDemo::mouse_drawing_demo(Mat& image)
{
	namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
	setMouseCallback("鼠标绘制",on_draw,(void*)(&image));
	imshow("鼠标绘制", image);
	temp = image.clone();
}

运行结果:

附:实时椭圆框图

static void on_draw(int event, int x, int y, int flag, void* userdata) {
	Mat image = *((Mat*)userdata);
	if (event == EVENT_LBUTTONDOWN) {
		sp.x = x;
		sp.y = y;
		cout << "start point :" << sp << 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);
			rectangle(image, box, Scalar(0, 255, 0), 2, 8, 0);*/
			RotatedRect c;
			c.center = sp;
			c.size = Size(dx, dy);
			c.angle = 0;
			ellipse(image, c, Scalar(225, 0, 0), 2, 8);
			imshow("鼠标绘制", image);
			//为下次绘制重置sp
			sp.x = -1;
			sp.y = -1;
		}
		
			
		cout << "end point :" << ep << endl;
	}
	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) {
				//为了使矩形不重复绘制,遮盖原图,每次都用克隆的临时原图来进行重置,消除上一步鼠标移动绘制出的矩形
				temp.copyTo(image);
				RotatedRect c;
				c.center = sp;
				c.size = Size(dx, dy);
				c.angle = 0;
				ellipse(image, c, Scalar(225, 0, 0), 2, 8);
				/*Rect box(sp.x, sp.y, dx, dy);
				rectangle(image, box, Scalar(0, 255, 0), 2, 8, 0);*/
				imshow("鼠标绘制", image);
			}
		}
	}
}

 结果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值