opencv#27 鼠标事件响应

鼠标事件响应函数

setMouseCallback()

void cv::setMouseCallback( const String &  winname,
                           MouseCallback   onMouse,
                           void*           userdata = 0
                         )

·winname:添加鼠标响应的窗口名字

·onMouse:鼠标响应的回调函数

·userdata:传递给回调函数的可选参数

用于检测鼠标事件,比如鼠标进行移动或者点击之类的操作,那么可以通过此函数进行检测,第一个参数时需要进行鼠标响应检测的显示图像的窗口,如果显示图像的命名为窗口,那么参数就要定义为窗口,也就是通过这个参数,我们知道鼠标的响应是与图片息息相关的,如果程序中没有显示图片,那么也就没有办法去检测鼠标的响应。

第二个参数是当鼠标进行了相应的操作之后,这个函数所启动的回调函数。

第三个参数,一般情况下我们可以不使用此参数。

响应的回调函数

MouseCallback()

typedef void(*cv::MouseCallback)(int event,int x,int y,int flags,void*userdata)

·event:鼠标响应事件标志,参数为EVENT_*形式。

·x:鼠标指针在图像中的x坐标。

·y:鼠标指针在图像坐标系中的y坐标。

·flags:鼠标响应标志,参数为EVENT_FLAG_*形式。

·userdata:传递给回调函数的可选参数。

第一个参数形式是EVENT_*形式,这里面的内容大多都是鼠标的瞬间操作,比如点击左键,右键,滑轮向前向后滚动。

第二,三个参数是鼠标在坐标系里的x坐标,y坐标。

第四个标志是鼠标响应标志,它的参数类型为EVENT_FLAG_*形式,多用于一种持续性动作的标志,比如按住左/右键拖拽等长时间存在的动作。

最后一个参数是传递给回调参数的可选参数,是与前面检测鼠标响应所相对应的,一般情况下可不使用。

鼠标响应事件标志

鼠标响应标志

 示例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv; //opencv的命名空间
using namespace std;


Mat img, imgPoint;
Point prePoint;//前一时刻鼠标的坐标,用于绘制直线
void mouse(int event, int x, int y, int flags, void*);

int main()
{
	img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/lenac.png");
	if (!img.data)
	{
		cout << "请确认输入图像名称是否正确" << endl;
		return -1;
	}
	img.copyTo(imgPoint);
	imshow("图像窗口1", img);
	imshow("图像窗口2", imgPoint);
	setMouseCallback("图像窗口1", mouse, 0);//鼠标响应

	waitKey(0);//等待函数用于显示图像
	return 0;

}

void mouse(int event, int x, int y, int flags, void*)
{
	if (event == EVENT_RBUTTONDOWN) //单击右键
	{
		cout << "点击鼠标左键才可以绘制轨迹" << endl;
	}
	if (event == EVENT_LBUTTONDOWN) //单击左键,输出坐标
	{
		prePoint = Point(x, y);
		cout << "轨迹起始坐标" << prePoint << endl;
	}
	if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)) //鼠标按住左键移动第3章图像基本操作
	{
		//通过绘制直线显示鼠标移动轨迹
		Point pt(x, y); //通过前一时刻的位置prePoint和当前时刻的位置pt绘制一条两点之间的线段
		line(img, prePoint, pt, Scalar(255, 255, 255), 2, 5, 0);
		prePoint = pt; //将当时时刻的位置,置为前一时刻的位置,用于下一步操作的结果
		imshow("图像窗口1", img);//将绘制的结果显示在图像中

		//通过改变图像像素显示鼠标移动轨迹,得到鼠标当前位置(x,y),分别将其四领域内的像素改为白色的像素
		imgPoint.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
		imgPoint.at<Vec3b>(y, x - 1) = Vec3b(255, 255, 255);
		imgPoint.at<Vec3b>(y, x + 1) = Vec3b(255, 255, 255);
		imgPoint.at<Vec3b>(y + 1, x) = Vec3b(255, 255, 255);
		imgPoint.at<Vec3b>(y + 1, x) = Vec3b(255, 255, 255);
		imshow("图像窗口2", imgPoint);
	}
}

结果

我们在图像1中快速拖拽左键,发现图像2中点很松散,说明在进行鼠标检测时,是需要时间的,如果在这个时间内移动了过多的像素位置。那么就没有办法将移动的中间那些区域改成白色,但是若使用的是两点之间的方法,那么我只需要知道每一次检测的时候,鼠标的坐标点即可,通过两个点就可以连接处一个轨迹。可以看出,若想绘制运动轨迹,最好的方式就是使用两点连线的形式,但是若鼠标移动的过慢,那么两种方法的结果是一样的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值