24.滑动条创建与鼠标响应

发布时间 2023-04-10 18:05:59作者: 夏蝉沐雪

1、创建图像窗口滑动条

代码清单3-54 createTrackbar()函数原型
1.  int cv::createTrackbar(const String & trackbarname,
2.                             const String & winname,
3.                             int * value,
4.                             int  count,
5.                             TrackbarCallback onChange = 0,
6.                             void * userdata = 0 
7.                             )
  • trackbarname:滑动条的名称

  • winname:创建滑动条窗口的名称。

  • value:指向整数变量的指针,该指针指向的值反映滑块的位置,创建后,滑块位置由此变量定义。

  • count:滑动条的最大取值。

  • onChange:每次滑块更改位置时要调用的函数的指针。该函数应该原型为void Foo(int,void *);,其中第一个参数是轨迹栏位置,第二个参数是用户数据。如果回调是NULL指针,则不会调用任何回调,只更新数值。

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

  该函数能够在图像窗口的上方创建一个范围从0开始的整数滑动条,由于滑动条只能输出整数,如果需要得到小数,必须进行后续处理,例如输出值除以10得到含有1位小数的数据。函数第一个参数是滑动条的名称,第二个参数是创建滑动条的图像窗口的名称。第三个参数是指向整数变量的指针,该指针指向的值反映滑块的位置,在创建滑动条时该参数确定了滑动块的初始位置,当滑动条创建完成后,该指针指向的整数随着滑块的移动而改变。第四个参数是滑动条的最大取值。第五个参数是每次滑块更改位置时要调用的函数的指针。该函数应该原型为void Foo(int,void *),其中第一个参数是轨迹栏位置,第二个参数是用户数据,如果回调是NULL指针,则不会调用任何回调,只更新数值。最后一个参数是传递给回调函数的void *类型数据,如果使用的第三个参数是全局变量,可以不用忽略最后一个参数,使用参数的默认值即可。

代码清单3-55 myCreateTrackbar.cpp在图像中创建滑条改变图像亮度
1.  #include <opencv2/opencv.hpp>
2.  #include <iostream>
3.  
4.  using namespace std;
5.  using namespace cv;
6.  
7.  //为了能在被调函数中使用,所以设置成全局的
8.  int value;
9.  void callBack(int, void*); //滑动条回调函数
10.  Mat img1, img2;
11.  
12.  int main()
13. {
14.    img1 = imread("lena.png");
15.    if (!img1.data)
16.    {
17.      cout << "请确认是否输入正确的图像文件" << endl;
18.      return -1;
19.    }
20.    namedWindow("滑动条改变图像亮度");
21.    imshow("滑动条改变图像亮度", img1);
22.    value = 100; //滑动条创建时的初值
23.    //创建滑动条
24.    createTrackbar("亮度值百分比", "滑动条改变图像亮度", &value, 600, callBack, 0);
25.    waitKey();
26.  }
27.  
28.  static void callBack(int, void*)
29. {
30.    float a = value / 100.0;
31.    img2 = img1 * a;
32.    imshow("滑动条改变图像亮度", img2);
33.  }

2、鼠标响应

代码清单3-56 setMouseCallback()函数原型
1.  void cv::setMouseCallback(const String & winname,
2.                                 MouseCallback onMouse,
3.                                 void * userdata = 0 
4.                                 )
  • winname:添加鼠标响应的窗口的名字

  • onMouse:鼠标响应的回调函数。

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

  该函数能够为指定的图像窗口创建鼠标响应。函数第一个参数是需要创建鼠标响应的图像窗口的名字。第二个参数为鼠标响应的回调函数,该函数在鼠标状态发生改变时被调用,是一个MouseCallback类型的函数。最后一个参数是传递给回调函数的可选参数,一般情况下使用默认值0即可。

代码清单3-57 MouseCallback类型原型
1.  typedef void(* cv::MouseCallback)(int  event,
2.                                           int  x,
3.                                           int  y,
4.                                           int  flags,
5.                                           void  *userdata
6.                                           )
  • event:鼠标响应事件标志,参数为EVENT_*形式,具体可选参数及含义在表3-9给出。

  • x:鼠标指针在图像坐标系中的x坐标

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

  • flags:鼠标响应标志,参数为EVENT_FLAG_*形式,具体可选参数及含义在表3-10给出。

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

  MouseCallback类型的回调函数是一个无返回值的函数,函数名可以任意设置,有五个参数,在鼠标状态发生改变的时候被调用。函数第一个参数是鼠标响应事件标志,参数为EVENT_*形式,具体可选参数及含义在表3-9给出。第二个和第三个参数分别是鼠标当前位置在图像坐标系中的x坐标和y坐标。第四个参数是鼠标响应标志,参数为EVENT_FLAG_*形式,具体可选参数及含义在表3-10给出。最后一个参数是传递给回调函数的可选参数,一般情况下用void*缺省即可。

表3-9 MouseCallback类型回调函数鼠标响应事件标志可选参数及含义

标志参数

简记

含义

EVENT_MOUSEMOVE

0

表示鼠标指针在窗口上移动

EVENT_LBUTTONDOWN

1

表示按下鼠标左键

EVENT_RBUTTONDOWN

2

表示按下鼠标右键

EVENT_MBUTTONDOWN

3

表示按下鼠标中键

EVENT_LBUTTONUP

4

表示释放鼠标左键

EVENT_RBUTTONUP

5

表示释放鼠标右键

EVENT_MBUTTONUP

6

表示释放鼠标中键

EVENT_LBUTTONDBLCLK

7

表示双击鼠标左键

EVENT_RBUTTONDBLCLK

8

表示双击鼠标右键

EVENT_MBUTTONDBLCLK

9

表示双击鼠标中间

EVENT_MOUSEWHEEL

10

正值表示向前滚动,负值表示向后滚动

EVENT_MOUSEHWHEEL

11

正值表示向左滚动,负值表示向右滚动

 

表3-10 MouseCallback类型回调函数鼠标响应标志及含义

标志参数

简记

含义

EVENT_FLAG_LBUTTON

1

按住左键拖拽

EVENT_FLAG_RBUTTON

2

按住右键拖拽

EVENT_FLAG_MBUTTON

4

按住中键拖拽

EVENT_FLAG_CTRLKEY

8

按下CTRL键

EVENT_FLAG_SHIFTKEY

16

按下SHIFT键

EVENT_FLAG_ALTKEY

32

按下ALT键

 

  鼠标响应简单来说就是当鼠标位于对应的图像窗口内时,时刻检测鼠标状态,当鼠标状态发生改变时调用回调函数,根据回调函数中的判断逻辑选择执行相应的操作。例如回调函数中只处理鼠标左键按下的事件,即判断event标志是否为EVENT_LBUTTONDOWN,只有当event==EVENT_LBUTTONDOWN时才有相应的逻辑操作,否则将不会执行任何操作。

代码清单3-58 myMouse.cpp绘制鼠标移动轨迹
1.  #include <opencv2/opencv.hpp>
2.  #include <iostream>
3.  
4.  using namespace std;
5.  using namespace cv;
6.  
7.  Mat img,imgPoint; //全局的图像
8.  Point prePoint; //前一时刻鼠标的坐标,用于绘制直线
9.  void mouse(int event, int x, int y, int flags, void*);
10.  
11.  int main()
12. {
13.    img = imread("lena.png");
14.    if (!img.data)
15.    {
16.      cout << "请确认输入图像名称是否正确!" << endl;
17.      return -1;
18.    }
19.    img.copyTo(imgPoint);
20.    imshow("图像窗口1", img);
21.    imshow("图像窗口2", imgPoint);
22.    setMouseCallback("图像窗口1", mouse,0 ); //鼠标影响
23.    waitKey(0);
24.    return 0;
25.  }
26.  
27.  void mouse(int event, int x, int y, int flags, void*)
28. {
29.    if (event == EVENT_RBUTTONDOWN) //单击右键
30.    {
31.      cout << "点击鼠标左键才可以绘制轨迹" << endl;
32.    }
33.    if (event == EVENT_LBUTTONDOWN) //单击左键,输出坐标
34.    {
35.      prePoint = Point(x, y);
36.      cout << "轨迹起使坐标" << prePoint << endl;
37.  
38.    }
39.    if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)) //鼠标按住左键移动
40.    {
41.      //通过改变图像像素显示鼠标移动轨迹
42.      imgPoint.at<Vec3b>(y, x) = Vec3b(0, 0, 255);
43.      imgPoint.at<Vec3b>(y, x-1) = Vec3b(0, 0, 255);
44.      imgPoint.at<Vec3b>(y, x+1) = Vec3b(0, 0, 255);
45.      imgPoint.at<Vec3b>(y+1, x) = Vec3b(0, 0, 255);
46.      imgPoint.at<Vec3b>(y+1, x) = Vec3b(0, 0, 255);
47.      imshow("图像窗口2", imgPoint);
48.  
49.      //通过绘制直线显示鼠标移动轨迹
50.      Point pt(x, y);
51.      line(img, prePoint, pt, Scalar(0, 0, 255), 2, 5, 0);
52.      prePoint = pt;
53.      imshow("图像窗口1", img);
54.    }
55.  }