24.滑动条创建与鼠标响应
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. }