一、键盘的响应

1.1 基本知识

  按键的读取只需要使用waitKey()函数就可以实现,十分简单。

1
int waitKey(int delay=0

  函数参数为延时时间(ms)
  delay<=0时,等待时间无限长,按下按键时函数结束,返回按键的键值。·
  delay>0时,等待delay毫秒按键响应,等待时间结束仍未按下按键则返回-1。

本人opencv4+vs2019实操时,没有按键时不返回值,有按键按下时返回对应键值。

1.2 确定按键响应值

  使用如下代码,可以测试自己的键盘对应的键值是多少。

1
2
3
4
5
6
void MyDemo::key_Demo(Mat& image) {
while(true) {
char k = waitKey(0);
std::cout << k << std::endl;
}
}

1.3 按键调节亮度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*按下1时:图片亮度增大
按下2时,图片亮度减小
按下q时,程序退出*/
void MyDemo::key_Demo(Mat& image) {
Mat m = Mat::zeros(image.size(),image.type());
m = Scalar(10, 10, 10); //增大或减小图片亮度的变化量
while(true) {
char k = waitKey(10);
if (k == 'q') { // Quit
break;
}
if (k == '1') { //Key 1
std::cout << "You enter key 1 - Lightness Up." << std::endl;
add(image, m, image);
}
if (k == '2') { //Key 2
std::cout << "You enter key 2 - Lightness Down." << std::endl;
subtract(image, m, image);
}
imshow("Key", image);
}
}

二、鼠标的响应

1.1 基本知识

  鼠标响应所使用的函数主要是 setMouseCallback()

1
2
3
4
5
void setMousecallback(
const string& winname, //窗口的名字
MouseCallback onMouse, //鼠标响应回调函数
void* userdata=0 //传给回调函数的参数
);

  其中onMouse响应回调函数函数,作用为指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为的原型如下:

1
2
3
4
5
6
7
void on_Mouse(
int event, //事件回传代号
int x, //鼠标指针在图像坐标系的坐标x
int y, //鼠标指针在图像坐标系的坐标y
int flags, //CV_EVENT_FLAG的组合
void* userdata //传递的参数
);
Event 作用
EVENT_MOUSEMOVE 滑动
EVENT_LBUTTONDOWN 左键点击
EVENT_RBUTTONDOWN 右键点击
EVENT_MBUTTONDOWN 中键点击
EVENT_LBUTTONUP 左键放开
EVENT_RBUTTONUP 右键放开
EVENT_MBUTTONUP 中键放开
EVENT_LBUTTONDBLCLK 左键双击
EVENT_RBUTTONDBLCLK 右键双击
EVENT_MBUTTONDBLCLK 中键双击

1.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
Point sp(-1, -1);	//起始点(初始值-1,-1)
Point ep(-1, -1); //结束点(初始值-1,-1)
Mat temp; //原图的克隆,用于实时刷新图片

static void on_draw(int event, int x, int y, int flags, void* userdata) {
Mat bg = *(Mat*)userdata; //回调函数传过来的图像数据
if (event == EVENT_LBUTTONDOWN) { //如果左键被按下
sp.x = x; //保存左键按下时的xy值
sp.y = y;
std::cout << "Start point: " << sp << std::endl;
}
else if (event == EVENT_LBUTTONUP) {//如果左键被抬起
ep.x = x; //保存左键抬起时的xy值
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(bg, box, Scalar(0, 0, 255), 2, 8, 0); //绘制矩形
imshow("Mouse Drawing", bg);
imshow("ROI", temp(box)); //显示ROI区域(被框选的区域)
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(bg); //刷新屏幕,清除上一循环绘制的矩形
rectangle(bg, box, Scalar(0, 0, 255), 2, 8, 0); //绘制新矩形
imshow("Mouse Drawing", bg);
}
}
}
}

void MyDemo::mouseDrawing_Demo(Mat& image) {
namedWindow("Mouse Drawing", WINDOW_AUTOSIZE); //创建一个窗口
setMouseCallback("Mouse Drawing", on_draw,(void*)(&image)); //调用鼠标回调函数
imshow("Mouse Drawing", image);
temp = image.clone();
}