OpenCV之鼠标操作
opencv中的鼠标响应的函数是setMouseCallback(),可以实现画图的功能。
c++
void setMousecallback(
const string& winname,
MouseCallback onMouse,
void* userdata=0
)
参数 | 解释 |
---|---|
winname | 窗口的名字 |
onMouse | 鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 |
userdate | 传给回调函数的参数 |
函数的原型应该为
typedef void (CV_CDECL *CvMouseCallback )
int event,
int x,
int flags,
);
第一个参数表示鼠标消息类型,取值如下:
enum
{
CV_EVENT_MOUSEMOVE =0,
CV_EVENT_LBUTTONDOWN =1,
CV_EVENT_RBUTTONDOWN =2,
CV_EVENT_MBUTTONDOWN =3,
CV_EVENT_LBUTTONUP =4,
CV_EVENT_RBUTTONUP =5,
CV_EVENT_MBUTTONUP =6,
CV_EVENT_LBUTTONDBLCLK =7,
CV_EVENT_RBUTTONDBLCLK =8,
CV_EVENT_MBUTTONDBLCLK =9
};
第二,三个参数表示鼠标的坐标。
第四个参数表示附加事件,取值如下:
enum
{
CV_EVENT_FLAG_LBUTTON =1,
CV_EVENT_FLAG_RBUTTON =2,
CV_EVENT_FLAG_MBUTTON =4,
CV_EVENT_FLAG_CTRLKEY =8,
CV_EVENT_FLAG_SHIFTKEY =16,
CV_EVENT_FLAG_ALTKEY =32
};
第五个参数即设置cvSetMouseCallback()中将接收到的参数
code1
绘制长方形
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "【程序窗口】"
// 描述:全局函数的声明
void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRectangle(cv::Mat& img, cv::Rect box);
//描述:全局变量的声明
Rect g_rectangle;
bool g_bDrawingBox = false;//是否进行绘制
RNG g_rng(12345);
int main(int argc, char** argv)
{
//改变console字体颜色
system("color 9F");
//准备参数
g_rectangle = Rect(-1, -1, 0, 0);
Mat srcImage(600, 800, CV_8UC3), tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-1, -1, 0, 0);
srcImage = Scalar::all(0);
//设置鼠标操作回调函数
namedWindow(WINDOW_NAME);
setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);
//程序主循环,当进行绘制的标识符为真时,进行绘制
while (1)
{
//拷贝源图到临时变量
srcImage.copyTo(tempImage);
//当进行绘制的标识符为真,则进行绘制
if (g_bDrawingBox) DrawRectangle(tempImage, g_rectangle);
imshow(WINDOW_NAME, tempImage);
if (waitKey(10) == 27) break;//按下ESC键,程序退出
}
return 0;
}
// 描述:鼠标回调函数,根据不同的鼠标事件进行不同的操作
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
Mat& image = *(cv::Mat*) param;
switch (event)
{
//鼠标移动消息
case EVENT_MOUSEMOVE:
{
if (g_bDrawingBox)//如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
}
break;
//左键按下消息
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_rectangle = Rect(x, y, 0, 0);//记录起始点
}
break;
//左键抬起消息
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;//置标识符为false
//对宽和高小于0的处理
if (g_rectangle.width < 0)
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0)
{
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
//调用函数进行绘制
DrawRectangle(image, g_rectangle);
}
break;
}
}
//描述:自定义的矩形绘制函数
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
cv::rectangle(img, box.tl(), box.br(), cv::Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//随机颜色
}
运行截图
code2
自由绘制
#include <opencv2/opencv.hpp>
using namespace std;
//隐藏命令行窗口
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
const char *pstrWindowsMouseDrawTitle = "绘图";
// 鼠标消息的回调函数
void on_mouse(int event, int x, int y, int flags, void* param)
{
static bool s_bMouseLButtonDown = false;
static CvPoint s_cvPrePoint = cvPoint(0, 0);
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
s_bMouseLButtonDown = true;
s_cvPrePoint = cvPoint(x, y);
break;
case CV_EVENT_LBUTTONUP:
s_bMouseLButtonDown = false;
break;
case CV_EVENT_MOUSEMOVE:
if (s_bMouseLButtonDown)
{
CvPoint cvCurrPoint = cvPoint(x, y);
cvLine((IplImage*)param, s_cvPrePoint, cvCurrPoint, CV_RGB(0, 0, 20), 3);
s_cvPrePoint = cvCurrPoint;
cvShowImage(pstrWindowsMouseDrawTitle, (IplImage*)param);
}
break;
}
}
int main()
{
const int MAX_WIDTH = 500, MAX_HEIGHT = 400;
//保存绘制的图像
const char *pstrSaveImageName = "MouseDraw.jpg";
IplImage *pSrcImage = cvCreateImage(cvSize(MAX_WIDTH, MAX_HEIGHT), IPL_DEPTH_8U, 3);
cvSet(pSrcImage, CV_RGB(255, 255, 255));
cvNamedWindow(pstrWindowsMouseDrawTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsMouseDrawTitle, pSrcImage);
cvSetMouseCallback(pstrWindowsMouseDrawTitle, on_mouse, (void*)pSrcImage);
int c;
do{
c = cvWaitKey(0);
switch ((char)c)
{
case 'r':
cvSet(pSrcImage, CV_RGB(255, 255, 255));
cvShowImage(pstrWindowsMouseDrawTitle, pSrcImage);
break;
case 's':
cvSaveImage(pstrSaveImageName, pSrcImage);
break;
}
}while (c > 0 && c != 27);
cvDestroyWindow(pstrWindowsMouseDrawTitle);
cvReleaseImage(&pSrcImage);
return 0;
}