opencv鼠标事件获取 图像处理操作(手动画线)
基本思路:
(1)读入一张图片
(2)设置鼠标监听事件,鼠标左键按下并且光标移动触发画点操作
(3)判断鼠标监听到的点是否是第一个点,第一个点只画圆(半径为1),后续的点画直线
(4)判断两次触发画点操作间隔的时间,如果时间大于阈值,重新设置当前点为起点
(5)不断更新显示这张图片(opencv画圆画线直接对图进行操作,操作后需要实时更新显示效果)
代码:
//***************************************************************************
//***************************************************************************
//鼠标操作在一张图片上面画线
//***************************************************************************
//***************************************************************************
#include<iostream>
#include<time.h>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>//图像处理的库,circle()要用到
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
Mat img;
Point p1, p2;
int point_num = 0;
clock_t previous=clock(),current;
double duration;
//*********************************************
//响应函数,在点击的地方画圆
//传递过来的参数:鼠标事件,鼠标事件发生处的坐标,FLAG
//********************************************
static void draw_circle(int event, int x, int y, int flags, void *)
{
if ((event == CV_EVENT_MOUSEMOVE)&&(flags&CV_EVENT_FLAG_LBUTTON))//鼠标左键按下并且光标移动
{
p2 = Point(x, y);
current = clock();//clock返回ms, time则返回s
duration = (double)(current - previous);//返回的是double类型的s
cout << duration << endl;
//如果停顿时间很长,则重新起点画线
if (duration > 200)//经验阈值200
{
point_num = 0;
}
cout << "Mouse Event" << endl;
//判断当前点是否是起点,起点只画圆,后续点画圆连线
if (point_num != 0)
{
//circle(img, p2, 1, Scalar(0, 0, 255)); //描以后的点
line(img, p1, p2, Scalar(0, 0, 255));//与前一点进行连线 参数:画图板背景、第一个点位置、第二个点位置、BGR颜色
}
else
{
circle(img, p2, 1, Scalar(0, 0, 255));//描第一个点 参数:画图板背景、原点的位置、半径、BGR颜色
}
p1 = p2;
previous = current;
point_num++;
}
}
int main()
{
img = imread("picture.png");
namedWindow("image");
setMouseCallback("image", draw_circle);//回调draw_circle(),获取鼠标信息
while (1)
{
imshow("image", img);
waitKey(30);
}
}
Tips
(1)用两次画线的点触发之间的时间间隔,判断是否要连续画线
(2)鼠标事件同时获取单击和光标移动,要用event配合flags
if ((event == CV_EVENT_MOUSEMOVE)&&(flags&CV_EVENT_FLAG_LBUTTON))//鼠标左键按下并且光标移动
效果: