开始之前
昨天写了具体的基本的图形绘制, 然后我们使用相应的函数接口进行调用, 便能够在图像上绘制出来相应的图形, 我们以图像绘制为例, 最终都会调用了 Line
函数, 最后都是基于一个 自定义迭代器 LineIterator
的形成的路径, 通过设定起始点和目标点, 相当于计算出来的斜率值, 每次累加的之后判断下一个点的位置, 通过 重载累加器的 ++
操作, 完成直线点指针的移动, 在相应的位置填入相应的颜色就可以得到 所要绘制的线, 这里是函数的调用图, 可放大查看细节部分
这里不再深入探讨, 相应的可以去研究具体的实现, 很漂亮的源码, 写的很好
我们这个章节 看一个比较高级点的操作, 操作起来比较复杂, 先不去深究其中的原理, 我们先跑起来, 然后再研究
正文
主要是处理鼠标的操作就好, 然后使用绘制图像就好, 可以参考博文《OpenCV:鼠标操作(绘制直线、矩形、圆)简单示例》
和博文OpenCV鼠标画图例程,鼠标绘制矩形,
鼠标绘制图像
我们先梳理一下逻辑, 我们使用两张图片作为轮换, 原始图和临时图, 每次绘制在临时图上, 然后完成之后存入原始图上
- 初始原始图像, 绘图标志 flg false
- 鼠标按下, 确定起始点 start_p 标志开始绘图
- 鼠标移动, 移动目标点 end_p, 绘制到临时图像上
- 鼠标抬起, 确定最后的点, 然后将图替换原始图, 同时 绘图标志结束flg = false
- 循环绘制图像, 绘图中的时候 显示临时图像, 绘图之后 显示原始图像,
逻辑理清除之后,我们就想要处理一下细节部分了, 我们在之前的博文中介绍了显示图像的方式, imshow
即可显示, 然后我们
发现问题在于程序的鼠标是件监听了, 这里其实比较深入了, 但是呢, 我们不深入去研究, 只去看实现的过程吧,
cv::setMouseCallback(windows_name, on_MouseHandle, 0);
, 我们第一个 windows_name
是我们打开的窗口名称, 用于显示图像, 也能通过名称进行句柄操作, 第二个参数就是我们的鼠标处理函数了, on_MouseHandle(int event, int x, int y, int flags, void *param)
, 这里的函数名称可以自定义, 但是参数类型与个数必须一致, 然后我们就可以通过预定义的事件宏进行确定当前鼠标操作的动作了, 这里 比如cv::EVENT_MOUSEMOVE
宏就是 鼠标移动事件, cv::EVENT_LBUTTONDOWN
,和cv::EVENT_LBUTTONUP
分别对应鼠标按下和鼠标抬起的操作, 命名写的很清楚
编码实现
我们在逻辑理清除 之后, 写起来就很简单了, 可以的大傲下面的代码, 注释也比较清除, 能够一看就懂
#include "mainwindow.h"
#include <QApplication>
// 引入 opencv 函数头文件
#include <opencv2/opencv.hpp>
// 记录鼠标位置点, 以及 正在绘图标志位 flg
cv::Point start_p(-1, -1), end_p(-1, -1);
bool flg_drawing = false;
// 使用原始图像与临时图像 存储
cv::Mat src_img, temp_img;
//鼠标回调函数 // 记录窗口的x y 位置
void on_MouseHandle(int event, int x, int y, int flags, void *param)
{
switch (event