opencv中鼠标函数的使用 及c++实现

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_40692109/article/details/102768949

鼠标事件函数介绍

opencv中进行鼠标操作主要用到setMouseCallback这个函数,如下:

 void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
 winname:窗口名称
 onMouse:鼠标响应函数,回调函数
 userdata:用户自定义的参数
 此函数会在调用之后不断查询鼠标信息直到窗口销毁

主要操作在回调函数onMouse中设置:


void on_Mouse(int event, int x, int y, int flags, void* param);

event:表示鼠标事件类型的常量

x和y:鼠标指针在图像坐标系的坐标

flags:鼠标事件标志的常量

param:用户可自定义的参数

鼠标事件的类型(字母和数字完全等价):

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         //中键双击

鼠标函数的应用

获取鼠标坐标:

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

using namespace cv;
using namespace std;

void on_Mouse(int event, int x, int y, int flags, void* param) {
	if (event == CV_EVENT_MOUSEMOVE)//鼠标移动将会触发此事件,CV_EVENT_MOUSEMOVE和0等效
	cout << "x:"<<x << "y:"<< y << endl;//鼠标在图片每移动一次就会输出一次坐标
}

int main()
{
	Mat src = imread("C:\\Users\\45374\\Desktop\\一些经典算法的代码整理\\code\\img\\lena.jpg");
	
	namedWindow("src");//创建窗口

	setMouseCallback("src", on_Mouse);//窗口名必须和之前创建窗口同名

	imshow("src", src);

	waitKey();
}

效果如下:

同理,如果将事件event改为CV_EVENT_MBUTTONDOWN或3,效果将是鼠标左键在图上点击一下,显示一次点击点坐标。 

鼠标框选感兴趣区域:

左键框选感兴趣区域:

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

Mat src,tmp,img,dst;//为了方便直接在这里初始化全局变量,也可以在mian函数中初始化通过鼠标函数中          
        //使用那个自定义的参数将图片传入回调函数,不过涉及一个Mat和指针类型的转换较为麻烦。

void on_Mouse(int event, int x, int y, int flags, void* param) {
	static Point pre_pt = Point(-1, -1);//起始点坐标,这里不加static会出错,是因为此回调函数会
        //在鼠标操作中不断执行很多次,如果不加static,起始点坐标将被不断重新赋值。
	static Point cur_pt = Point(-1, -1);//终点坐标
	if (event == 1)
	{
		pre_pt = Point(x, y);//左键按下,记录起始点坐标
		cout << pre_pt << endl;
	}
	else if (event == CV_EVENT_MOUSEMOVE && flags == 1) {
                //左键不放鼠标移动过程中实时显示框选区域
		src.copyTo(tmp);
		cur_pt = Point(x, y);
		rectangle(tmp, pre_pt, cur_pt, Scalar(255, 255, 0, 0), 1, 8, 0);
		//cout << cur_pt << endl;//实时显示坐标
		imshow("src", tmp);//画的时候显示框
	}

	else if (event == 4)
	{
		src.copyTo(img);
		cur_pt = Point(x, y);
		cout << cur_pt << endl;
		rectangle(img, pre_pt, cur_pt, Scalar(255, 255, 0, 0), 1, 8, 0);
		int width = abs(pre_pt.x - cur_pt.x);
		int height = abs(pre_pt.y - cur_pt.y);
		dst = src(Rect(min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height));

		namedWindow("dst", CV_WINDOW_NORMAL);//CV_WINDOW_NORMAL可自由调整图片大小
		imshow("dst", dst);//显示所框出的感兴趣区域
		//imwrite("E:/img/lina.bmp", dst);
	}
}

int main()
{
	src = imread("C:\\Users\\45374\\Desktop\\一些经典算法的代码整理\\code\\img\\lena.jpg");
	
	namedWindow("src");
	
	setMouseCallback("src", on_Mouse,0);

	imshow("src", src);//imshow和setMouseCallback位置关系没有要求,setMouseCallback只有当窗口销毁之后才会停止。

	waitKey(0);
}

效果如下:

注意上面有个src.copyTo(tmp);的过程,因为每次画框之后的框是无法去除的,所以框选过程中每次都需新创建一个图片来显示实时框选过程,如果不将src的图像拷贝到tmp中再进行操作,就会出现如下效果:

猜你喜欢

转载自blog.csdn.net/qq_40692109/article/details/102768949