OpenCV的鼠标操作——用鼠标画矩形(代码解读)
2017-08-07 10:36
204 查看
起因
知乎上被邀请回答一个问题,关于OpenCV的鼠标操作的问题。我发现回答下来写了不少东西,可以整理为一篇文章发出来,顺便说下不少人关心的如何用操作鼠标,比如如何用鼠标在图像上画一个矩形或者说选择一个矩形的ROI。知乎上的问题问的是下面这段代码是什么意思。
正好,这段代码我是看过的,而且就在最近两周。所以正好可以说道一下。
介绍
这一段代码我最初是在contrib模块里面tracking模块的samples里面看到的,出自roiSelector.hpp。这个文件的作用就是用鼠标在图片中选择一个矩形区域。感兴趣的读者可以到这里知道源代码。为了照顾一部分人,更加直白的说法是这段代码在下面这样的路径下:opencv3.2\opencv_contrib-master\modules\tracking\samples
注意,这里是opencv contrib模块,不是官网下载的那个OpenCV.
显然,我们知道要用一个鼠标选择一个矩形区域,鼠标的运动可以细分为一下三个动作:
鼠标左键按下
鼠标非水平非垂直地滑动
鼠标左键抬起。
在
roiSelector.hpp的代码中,在处理
EVENT_LBUTTONUP(鼠标左键抬起事件)之前,还分别先对
EVENT_LBUTTONDOWN(鼠标左键按下事件)和
EVENT_MOUSEMOVE(鼠标移动事件)进行了处理。
为了说明题主给出的代码的具体含义,必须先明白前两个事件,也即鼠标左键按下和鼠标滑动,都是怎么处理的。为了方便说明,这里不讨论代码中从矩形中心开始画矩形的情况,我把这三个事件的代码简化如下,为了放方便说明,调整了顺序:
PS:加一句也许是废话的话,在OpenCV中,矩形的表示方式是(x,y,width,height),也即是矩形框左上角坐标,外加宽高。而OpenCV的图像坐标系也是以图像左上角为原点,越往右x越大,越往下y越大。
代码解读
代码经过了简化,但是应该已经足够说明问题。简化后的代码如下:
switch (event) { // start to select the bounding box case cv::EVENT_LBUTTONDOWN: data->isDrawing = true; data->box = cv::Rect2d(x, y, 0, 0); break; // update the selected bounding box case cv::EVENT_MOUSEMOVE: if (data->isDrawing) { data->box.width = x - data->box.x; data->box.height = y - data->box.y; } break; // cleaning up the selected bounding box case cv::EVENT_LBUTTONUP: data->isDrawing = false; if (data->box.width < 0) { data->box.x += data->box.width; data->box.width *= -1; } if (data->box.height < 0) { data->box.y += data->box.height; data->box.height *= -1; } break; }
case 1
这里先说第一个case,也即第一个动作,鼠标左键按下事件:EVENT_LBUTTONDOWN。// 若鼠标左键按下,则矩形初始化为以鼠标当时坐标为左上角坐标,宽高都为0的矩形。 // 且开始画flag为真,左键不按下滑动鼠标则不会开始画。
case cv::EVENT_LBUTTONDOWN: data->isDrawing = true; data->box = cv::Rect2d(x, y, 0, 0); break;
case 2
第二个case,也即第二个动作,鼠标滑动事件:EVENT_MOUSEMOVE。// 如果鼠标开始滑动,更新矩形的宽高。 // 用滑动时鼠标所在的坐标x减去初始的x为矩形的宽度。 // 坐标y减去矩形初始的y为矩形的宽。 // 比如鼠标往左水平移动了5个像素,那么宽为5px。 // 鼠标垂直向下移动了10个像素,那么矩形高为10px。
case cv::EVENT_MOUSEMOVE: if (data->isDrawing) { data->box.width = x - data->box.x; data->box.height = y - data->box.y; } break;
case 3
// cleaning up the selected bounding box // 无视上面这句英文。 // 这里最后的一个动作,鼠标左键抬起(释放)。 // 如果矩形宽小于0,结合前面说的OpenCV的坐标系方向, // 说明鼠标滑动的时候是从右往左滑动的,所以这个时候原本鼠标左键按下的起始点 // 就不再是矩形的左上角的点,所以需要用原本的x减去矩形宽度 // 才是现在的矩形的左上角的x坐标。由于此时宽度为负数,所以下面用加号表示相减。 // 然后乘以-1使得宽度从负数变成正数。 // 下面的高度为负同理。 // 这里用两个if而不是if...else...的原因就是隐含如果宽高不为负, // 那么最后的宽高就是鼠标释放的时候坐标减去初始左上角坐标的得到的宽高。
case cv::EVENT_LBUTTONUP: data->isDrawing = false; if (data->box.width < 0) { data->box.x += data->box.width; data->box.width *= -1; } if (data->box.height < 0) { data->box.y += data->box.height; data->box.height *= -1; } break; }
公众号CVPy,分享OpenCV和Python的实战内容。。欢迎关注。
相关文章推荐
- 用鼠标画矩形的win32代码
- matlab 用鼠标拖曳画矩形的代码
- live555代码解读
- 解读Helloworld的代码
- 声波通信(SinVoice)代码解读(一) 如何产生给定频率的声音
- js与jquery中获取当前鼠标的x、y坐标位置的代码
- 使用JS或jQuery模拟鼠标点击a标签事件代码
- live555代码解读之三:SETUP和PLAY请求消息处理过程
- 鼠标滑过图片出现大图片提示层效果js代码
- VB代码窗口鼠标滚轮的使用
- 【代码片段】双语导航/导航中鼠标经过变换文字
- 基于jquery的不规则矩形的排列实现代码
- SWT事件到Draw2d事件转化的代码解读
- Android文件清单AndroidManifest.xml代码解读
- lldpd-0.7.7代码解读(send_pdu部分)
- eclipse 去掉鼠标移动代码提示
- 免费CSS鼠标样式代码大全
- 鼠标移动提示的广告代码:如何实现广告随鼠标移动提示(转)
- Css实现的鼠标滑动选项卡菜单代码
- 可以用鼠标拖动的DIV实现思路及代码