OPENCV图像处理基础(五)鼠标事件画个框

在GUI编程中会涉及到鼠标事件,通过鼠标事件可以使得人和机器的交互更为便捷。opencv中提供了一种以回调函数实现的鼠标事件机制。
下面是一个例子,通过鼠标在一张图片上画出任意大小的矩形框。
效果如下:
程序运行图

#include<iostream>
#include<opencv2\opencv.hpp>
using namespace cv;
using namespace std;

Rect box;//矩形对象
bool drawing_box;//记录是否在画矩形对象

void onmouse(int event, int x, int y, int flag, void *img)//鼠标事件回调函数,鼠标点击后执行的内容应在此
{
    switch (event)
    {
    case CV_EVENT_LBUTTONDOWN://鼠标左键按下事件
            drawing_box = true;//标志在画框
            box = Rect(x, y, 0, 0);//记录矩形的开始的点
            break;
    case CV_EVENT_MOUSEMOVE://鼠标移动事件
        if (drawing_box){//如果左键一直按着,则表明在画矩形
            box.width = x - box.x;
            box.height = y - box.y;//更新长宽
        }
            break;
    case CV_EVENT_LBUTTONUP://鼠标左键松开事件
        drawing_box = false;//不在画矩形
        //这里好像没作用
        if (box.width<0){//排除宽为负的情况,在这里判断是为了优化计算,不用再移动时每次更新都要计算长宽的绝对值
            box.x = box.x + box.width;//更新原点位置,使之始终符合左上角为原点
            box.width = -1 * box.width;//宽度取正
        }
        if (box.height<0){//同上
            box.y = box.y + box.height;
            box.height = -1 * box.width;
        }   
        break;
    default:
        break;
    }
}
int main()
{
    Mat img = imread("beach.jpg");//读取图像
    Mat temp;
    namedWindow("鼠标画个框");//窗口
    setMouseCallback("鼠标画个框", onmouse,&img);//注册鼠标事件到“鼠标画个框”窗口,即使在该窗口下出现鼠标事件就执行onmouse函数的内容,最后一个参数为传入的数据。这里其实没有用到
    imshow("鼠标画个框", img);
   //img.copyTo(temp);放在这里会出现拖影的现象,因为上一次画的矩形并没有被更新
    while (1)
    {
        //img.copyTo(temp);//这句话放在if外,注释掉if里面那句.程序没有问题,但每次遍历循环时都会执行一次图像数据的复制传递操作,这是不必要。在高速的PC上没关系,但在嵌入式系统中时,可能会因为硬件性能而无法满足实时需求。因此不建议放这里咯
        //只要不再次按下鼠标左键触发事件,则程序显示的一直是if条件里面被矩形函数处理过的temp图像,如果再次按下鼠标左键就进入if,不断更新被画矩形函数处理过的temp,因为处理速度快所以看起来画矩形的过程是连续的没有卡顿,因为每次重新画都是在没有框的基础上画出新的框因为人眼的残影延迟所以不会有拖影现象。每次更新矩形框的传入数据是重新被img(没有框)的数据覆盖的temp(即img.data==temp.data)和通过回调函数更新了的Box记录的坐标点数据。
        //依照上面所述,则当画完一个矩形后,如果在单击一下鼠标左键(没有拖动),则drawing_box==true,因为Box记录到的坐标点数据计算出来的长宽为0(因为未进行拖动,box.width,box.height为0,则画矩形函数rectangle()所传入第二第三个参数即对角点的参数两个是相等的,所以矩形的对角线是0就无法画出矩形),则显示的是没有框的原图,此时显示的temp的数据应是和img相等的
        if (drawing_box){//不断更新正在画的矩形
            img.copyTo(temp);//这句放在这里是保证了每次更新矩形框都是在没有原图的基础上更新矩形框。
            rectangle(temp,Point(box.x, box.y),Point(box.x+box.width,box.y+box.height),Scalar(255,255,255));
            imshow("鼠标画个框",temp);//显示
        }

        if (waitKey(30) == 27) {//检测是否有按下退出键
            break;//退出程序
        }
    }

    return 0;
}

至此。

注:本人才疏学浅,欢迎指正。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值