实验环境:
Windows10 x64
vs2013 + openCV2.4.11
实验目的:
通过实验体会openCV实现的对鼠标事件处理的设置回调函数setMouseCallback的使用,体会其中的用处以及openCV定义的鼠标事件宏,理解回调函数的函数指针定义形式及参数意义,并通过画图函数line,rectangle等体会绘图函数的使用;
实验代码:
// OpenCV对鼠标事件的处理
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
/*
1:事件宏定义
enum
{
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
};
2:回调函数的定义方式(函数指针)
typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata);
//! assigns callback for mouse events
CV_EXPORTS void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata = 0);
3:画线函数
line
Draws a line segment connecting two points.
C++: void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
4:画矩形函数
rectangle
Draws a simple, thick, or filled up-right rectangle.
C++: void rectangle(Mat& img, Rect rec, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
*/
int pos_x1 = 0;
int pos_y1 = 0;
int pos_x2 = 0;
int pos_y2 = 0;
int flag = 0;
static void onMouse(int event, int x, int y, int, void*)
{
if (event == EVENT_LBUTTONDOWN || event == EVENT_MOUSEMOVE || event == EVENT_RBUTTONDOWN)
{
return;
}
if (flag == 0)
{
pos_x1 = x;
pos_y1 = y;
flag = 1;
}
if (flag == 1)
{
pos_x2 = x;
pos_y2 = y;
flag = 2;
}
cout << "用户点击图像: 位置 " << x << ": " << y << endl;
}
int main()
{
VideoCapture cap("E:\\video\\1.avi");
if (!cap.isOpened())
{
cout << "无法打开视频文件" << endl;
return -1;
}
namedWindow("mouseCallback");
setMouseCallback("mouseCallback", onMouse);
while (1)
{
Mat frame;
bool bRead = cap.read(frame);
if (!bRead)
{
cout << "视频文件读取完成" << endl;
break;
}
if (flag == 2)
{
//line(frame, Point(pos_x1, pos_y1), Point(pos_x2, pos_y2), CV_RGB(255, 0, 255), 10);
rectangle(frame, Rect(Point(pos_x1, pos_y1), Point(pos_x2, pos_y2)), CV_RGB(0, 0, 255));
}
imshow("mouseCallback", frame);
if (waitKey(33) >= 0)
{
break;
}
}
cap.release();
destroyAllWindows();
}
程序运行效果:
思考:
1:这种回调与绘图函数结合的应用是什么?
我的理解是在比如车辆检测中,有些算法是通过虚拟线或虚拟矩形框的方法进行检测,通过这个示例可以运用于比如车辆检测中根据摄像机拍摄到的视频的角度进行动态的设置用于检测的虚拟线或虚拟矩形框,让程序有较好的灵活性;
2:通过回调函数可以灵活的获取某一帧的信息,如帧的序列号等;