【OpenCV + VS】如何使用鼠标在图像上绘制

在图像处理和计算机视觉应用中,鼠标交互是一个非常常见的功能。我们可以利用鼠标事件来绘制矩形、圆形、线条等,或者选择图像的感兴趣区域(ROI)。在 OpenCV 中,我们可以通过设置鼠标回调函数来处理这些交互。

1. OpenCV 鼠标事件概述

OpenCV 提供了
setMouseCallback()
函数,用于设置鼠标事件的回调函数。通过不同的鼠标事件,您可以处理鼠标按下、松开和移动等行为。常见的鼠标事件包括:


EVENT_LBUTTONDOWN
:鼠标左键按下。


EVENT_LBUTTONUP
:鼠标左键释放。


EVENT_MOUSEMOVE
:鼠标移动。


EVENT_RBUTTONDOWN
:鼠标右键按下。

这些事件通过回调函数传递给我们,我们可以在回调函数中根据事件类型做出不同的响应。

2. 鼠标绘制示例

下面是一个完整的 OpenCV 示例,演示如何使用鼠标绘制矩形。用户按下鼠标左键开始绘制,松开鼠标左键结束绘制。在鼠标移动时,会实时更新矩形的大小。

示例代码


#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
 
Point sp(-1, -1);  // 起始点
Point ep(-1, -1);  // 结束点
Mat temp;          // 用于保存图像副本
 
// 鼠标回调函数
static void on_draw(int event, int x, int y, int flags, void* userdata) {
    Mat image = *((Mat*)userdata);
 
    if (event == EVENT_LBUTTONDOWN) {  // 按下鼠标左键
        sp.x = x;  // 记录起始点的横坐标
        sp.y = y;  // 记录起始点的纵坐标
        std::cout << "Start point: " << sp << std::endl;
    }
    else if (event == EVENT_LBUTTONUP) {  // 松开鼠标左键
        ep.x = x;  // 记录结束点的横坐标
        ep.y = y;  // 记录结束点的纵坐标
        int dx = ep.x - sp.x;  // 计算矩形的宽度
        int dy = ep.y - sp.y;  // 计算矩形的高度
        if (dx > 0 && dy > 0) {
            Rect box(sp.x, sp.y, dx, dy);  // 计算矩形区域
            rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);  // 绘制矩形
            imshow("Mouse Drawing", image);  // 显示图像
            imshow("ROI Area", image(box));  // 显示选定的ROI区域
        }
    }
    else if (event == EVENT_MOUSEMOVE) {  // 鼠标移动时
        if (sp.x > 0 && sp.y > 0) {  // 确保已经按下鼠标
            ep.x = x;  // 更新结束点的横坐标
            ep.y = y;  // 更新结束点的纵坐标
            int dx = ep.x - sp.x;  // 计算矩形的宽度
            int dy = ep.y - sp.y;  // 计算矩形的高度
            if (dx > 0 && dy > 0) {
                temp.copyTo(image);  // 将原图恢复
                Rect box(sp.x, sp.y, dx, dy);  // 计算矩形区域
                rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);  // 绘制矩形
                imshow("Mouse Drawing", image);  // 显示图像
            }
        }
    }
}
 
// 鼠标绘制演示
void mouse_drawing_demo(Mat& image) {
    namedWindow("Mouse Drawing", WINDOW_AUTOSIZE);  // 创建窗口
    setMouseCallback("Mouse Drawing", on_draw, (void*)(&image));  // 设置鼠标回调
    imshow("Mouse Drawing", image);  // 显示图像
    temp = image.clone();  // 备份原图
}
 
int main() {
    // 读取图像
    Mat image = imread("your_image_path_here.jpg");  // 使用您自己的图像路径
    if (image.empty()) {
        std::cout << "无法加载图像!" << std::endl;
        return -1;
    }
 
    mouse_drawing_demo(image);  // 开启鼠标绘制功能
 
    waitKey(0);  // 等待用户按键
    destroyAllWindows();  // 关闭窗口
    return 0;
}

3. 代码详解

3.1 读取图像并创建窗口


Mat image = imread("your_image_path_here.jpg");  // 读取图像
if (image.empty()) {
    std::cout << "无法加载图像!" << std::endl;
    return -1;
}


imread()
用于读取图像文件。若文件路径正确且图像加载成功,
image.empty()
将返回
false

3.2 设置鼠标回调函数

setMouseCallback("Mouse Drawing", on_draw, (void*)(&image));


setMouseCallback()
设置一个回调函数,当用户在窗口中执行鼠标操作时,OpenCV 将调用这个回调函数。在本例中,回调函数是
on_draw

3.3 鼠标回调函数的处理

回调函数
on_draw
根据不同的鼠标事件进行处理:


EVENT_LBUTTONDOWN
:当左键按下时,记录起始点的坐标。


EVENT_LBUTTONUP
:当左键松开时,记录结束点的坐标,并绘制矩形。


EVENT_MOUSEMOVE
:当鼠标移动时,实时更新矩形的大小。

在绘制矩形时,我们使用
rectangle()
函数来绘制一个矩形,
Scalar(0, 0, 255)
表示矩形的颜色是红色。

3.4 显示图像


imshow("Mouse Drawing", image);
imshow("ROI Area", image(box));  // 显示矩形区域


imshow()
用来显示当前图像。在矩形绘制过程中,矩形区域会被实时显示,并且用户可以看到矩形随鼠标移动而动态变化。

3.5 恢复图像并绘制矩形


temp.copyTo(image);  // 恢复图像
rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);


copyTo()
用来将原图恢复,以便用户在绘制矩形时不会影响其他区域。

4. 总结

通过鼠标事件,我们可以实现与图像的交互操作,例如绘制矩形、选择感兴趣区域(ROI)等。这种功能在许多图像处理应用中都非常有用,如手动标注数据、裁剪图像等。OpenCV 提供了简单易用的
setMouseCallback()
和鼠标事件处理机制,让我们能够快速实现鼠标交互。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
清风以北的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容