OpenCV4入门系列教程22:鼠标操作

索引地址:系列教程索引地址

上一篇:OpenCV4入门系列教程21:滑动栏

鼠标操作

GUI中鼠标操作不太常用,至少我还没有太多用过,或许是因为我技术太菜。

和滑动栏类似,依附于窗口,设置回调函数,在回调函数中设置主要功能。

函数原型:

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

参数说明:

  • 第一个参数是窗口名,如果已经使用过imshow就是直接把其窗口名写入就可以了。如果没有,则需要声明一个,否则编译会报错。声明为namedWindow("name")
  • 第二个参数是回调函数名,任意。
  • 第三个是数据指针,需要处理的图像。

测试1

一个空鼠标操作代码如下,只是输出当前鼠标坐标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void on_MouseHandle(int event,int x,int y,int flags, void *param);//回调函数

int main(){
Mat srcImage=imread("lena.jpg");//读取图片数据
//cout<<srcImage<<endl;

namedWindow("mouse");//创建窗口
setMouseCallback("mouse",on_MouseHandle,(void *)&srcImage);//设置鼠标窗口,回调函数

imshow("mouse",srcImage);

waitKey();
}

void on_MouseHandle(int event,int x,int y,int flags, void *param){
cout<<"current pos is: "<<x<<" "<<y<<endl;
}

效果如图:

鼠标在图片上,就会输出坐标。

测试2

使用鼠标绘图

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//--------------------------------------【程序说明】-------------------------------------------
// 程序说明:《OpenCV3编程入门》OpenCV2版书本配套示例程序18
// 程序描述:HelloOpenCV
// 2014年11月 Created by @浅墨_毛星云
// 2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】-----------------------------
// 描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include <opencv2/opencv.hpp>
using namespace cv;

//-----------------------------------【宏定义部分】--------------------------------------------
// 描述:定义一些辅助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME "mouse" //为窗口标题定义的宏

//-----------------------------------【全局函数声明部分】------------------------------------
// 描述:全局函数的声明
//------------------------------------------------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void *param);
void DrawRectangle(cv::Mat &img, cv::Rect box);
void ShowHelpText();

//-----------------------------------【全局变量声明部分】-----------------------------------
// 描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Rect g_rectangle;
bool g_bDrawingBox = false; //是否进行绘制
RNG g_rng(12345);

//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-------------------------------------------------------------------------------------------------
int main(int argc, char **argv) {

//【0】显示欢迎和帮助文字
ShowHelpText();

//【1】准备参数
g_rectangle = Rect(-1, -1, 0, 0);
Mat srcImage(600, 800, CV_8UC3), tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-1, -1, 0, 0);
srcImage = Scalar::all(0);

//【2】设置鼠标操作回调函数
namedWindow(WINDOW_NAME);
setMouseCallback(WINDOW_NAME, on_MouseHandle, (void *)&srcImage);

//【3】程序主循环,当进行绘制的标识符为真时,进行绘制
while (1) {
srcImage.copyTo(tempImage); //拷贝源图到临时变量
if (g_bDrawingBox)
DrawRectangle(tempImage, g_rectangle); //当进行绘制的标识符为真,则进行绘制
imshow(WINDOW_NAME, tempImage);
if (waitKey(10) == 27)
break; //按下ESC键,程序退出
}
return 0;
}

//--------------------------------【on_MouseHandle( )函数】-----------------------------
// 描述:鼠标回调函数,根据不同的鼠标事件进行不同的操作
//-----------------------------------------------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void *param) {

Mat &image = *(cv::Mat *)param;
switch (event) {
//鼠标移动消息
case EVENT_MOUSEMOVE: {
if (g_bDrawingBox) //如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
} break;

//左键按下消息
case EVENT_LBUTTONDOWN: {
g_bDrawingBox = true;
g_rectangle = Rect(x, y, 0, 0); //记录起始点
} break;

//左键抬起消息
case EVENT_LBUTTONUP: {
g_bDrawingBox = false; //置标识符为false
//对宽和高小于0的处理
if (g_rectangle.width < 0) {
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}

if (g_rectangle.height < 0) {
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
//调用函数进行绘制
DrawRectangle(image, g_rectangle);
} break;
}
}

//-----------------------------------【DrawRectangle( )函数】------------------------------
// 描述:自定义的矩形绘制函数
//-----------------------------------------------------------------------------------------------
void DrawRectangle(cv::Mat &img, cv::Rect box) {
cv::rectangle(
img, box.tl(), box.br(),
cv::Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255))); //随机颜色
}

void ShowHelpText() {//输出一些帮助信息
printf("\n\n\n\t欢迎来到【鼠标交互演示】示例程序\n");
printf("\n\n\t请在窗口中点击鼠标左键并拖动以绘制矩形\n");
}

主要功能演示如下:

下一篇:OpenCV4入门系列教程23:Qt格式的按钮