文章目录
opencv鼠标事件函数setmousecallback()详解
1、鼠标事件函数:
(1)鼠标事件函数原型:setmousecallback(),此函数会在调用之后不断查询回调函数onmouse(),直到窗口销毁
void setmousecallback(
const string& winname,
mousecallback onmouse,
void* userdata = 0
)
参数解释:
winname:窗口名称;
onmouse:回调函数;
userdata:传递给回调函数用户自定义的外部数据,userdata是一个 void 类型的指针;
(2)回调函数onmouse(),可随意命名,但是要与 setmousecallback()函数里的回调函数名称一致
void onmouse(
int event,
int x,
int y,
int flags,
void *userdata
)
参数解释:
event:表示鼠标事件类型的常量(
#define cv_event_mousemove 0 //滑动
#define cv_event_lbuttondown 1 //左键点击
#define cv_event_rbuttondown 2 //右键点击
#define cv_event_mbuttondown 3 //中键点击
#define cv_event_lbuttonup 4 //左键放开
#define cv_event_rbuttonup 5 //右键放开
#define cv_event_mbuttonup 6 //中键放开
#define cv_event_lbuttondblclk 7 //左键双击
#define cv_event_rbuttondblclk 8 //右键双击
#define cv_event_mbuttondblclk 9 //中键双击
);
x和y:鼠标指针在图像坐标系的坐标;
flags:鼠标事件标志的常量;
userdata:回调函数接收,用户自定义的外部数据,userdata是一个 void 类型的指针;
2、代码示例:
(1)main.cpp
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>
using namespace cv;
using namespace std;
int main() {
//读取图像,bgr存储在mat矩阵里
mat src = cv::imread("c:\\cpp\\image\\suzy4.jpg");
if (src.empty()) {
printf("could not load image..../n");
return -1;
}
demo demo;
demo.mouseevent(src);
waitkey();
destroyallwindows();
return 0;
}
(2)头文件demo.h
#include <opencv2/opencv.hpp>
using namespace cv;
class demo
{
public:
void mouseevent(mat &image);
private:
};
(3)demo.cpp
#include <demo.h>
using namespace std;
point sp(-1, -1);
point ep(-1, -1);
mat temp;
static void onmouse(int event, int x, int y, int flags, void *userdata) {
/**
* 对指针userdata,进行转换和解引用的操作,将userdata指向的mat对象,赋值给名为image的变量,以便后续对图像数据的处理:
* userdata是一个void类型的指针,需要转换为mat类型的指针,然后用*运算符解引用,得到mat对象,再赋值给名为image的变量,这样就可以对image进行操作了;
*/
mat image = *((mat*)userdata);
if (event == event_lbuttondown) {
// 起点坐标
sp.x = x;
sp.y = y;
std::cout << "start point:" << sp << std::endl;
}
else if (event == event_lbuttonup) {
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(image);
imshow("roi区域", image(box));
rectangle(image, box, scalar(0, 0, 255), 2, 8, 0);
imshow("鼠标绘制", image);
// ready for next drawing
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(image);
rectangle(image, box, scalar(0, 0, 255), 2, 8, 0);
imshow("鼠标绘制", image);
}
}
}
}
void demo::mouseevent(mat &image) {
namedwindow("鼠标事件", window_autosize);
/**
* 由于回调函数需要传入的是一个void类型指针,我们先取image的地址,再将&image强制转换为void类型指针,具体操作如下:
* &image:获取变量image的内存地址,即mat对象的指针;
* (void*):是一个强制类型转换,将image的地址转换为void类型指针,这样就可以将参数传递给回调函数了;
*/
setmousecallback("鼠标绘制", onmouse, (void*)(&image));
imshow("鼠标绘制", image);
temp = image.clone();
}
发表评论