本人也是兴趣了解opencv,在空闲时间看opencv3编程入门的这本书籍,通过博客加深学习的印象,分享学习中的问题。
OpenCv中的鼠标操作和滑动条的消息映射方式类似
SetMouseCallback 函数的作用是为指定的窗口设置鼠标回调函数
Void setMouseCallback(const string& winname,MouseCalllback onMouse,void* userdata = 0)
第一个参数,const string& 类型的 winname,窗口的名字。
第二个参数,MouseCallback类型的 onMouse,指定窗口里每次鼠标事件发生的时候,被调用的函数指针。
这个函数的原型的大概形式为 void Foo(int event,int x,int y,int flags,void* param).
其中event是EVENT_+变量之一,X和Y是鼠标指针在图像坐标系()中的坐标值,flags是EVENT_FLAG的组合,param 是用户定义的传递到SetMouseCallback函数调用的参数,如EVENT_MOUSEMOVE为鼠标移动消息,EVENT_LBUTTONDOWN为鼠标左键按下消息等。
在OpenCv2中,上述“EVENT_”之前可以加上“CV_”前缀。
第三个参数,void*类型的userdata,用户定义的传递到回调函数的参数,有默认值0.
下面看代码中实现过程:
#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); //在临时变量的图片上绘制矩形
void ShowHelpText();
//全局变量声明部分
Rect g_rectanle;
bool g_bDrawingBox = false; //是否进行绘制
RNG g_rng(12345);
//main函数
int main(int argc, char** argv)
{
//准备参数
g_rectanle = Rect(-1,-1,0,0);
Mat srcImage(600,800,CV_8UC3), tempImage;
srcImage.copyTo(tempImage); //复制源图到临时变量
g_rectanle = 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_rectanle); //当绘制的标示符为真,则进行绘制
}
imshow(WINDOW_NAME, tempImage);
imwrite("123.jpg", tempImage);
if (waitKey(10) == 27)
{
break;
}
}
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_rectanle.width = x - g_rectanle.x;
g_rectanle.height = y - g_rectanle.y;
}
}
break;
//左键按下
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_rectanle = Rect(x, y, 0, 0); //记录起始点
}
break; // 起初此处遗漏掉了break;造成只能绘制出随机颜色的点,不能绘制矩形
//左键抬起消息
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;//置标示符为false
//对宽和高小于0的处理
if (g_rectanle.width < 0)
{
g_rectanle.x += g_rectanle.width;
g_rectanle.width *= -1;
}
if (g_rectanle.height < 0)
{
g_rectanle.y += g_rectanle.height;
g_rectanle.height *= -1;
}
//调用函数进行绘制
DrawRectangle(image, g_rectanle);
}
break;
default:
break;
}
}
//自定义的矩形绘制函数
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0,255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
}