OpenCV鼠标事件

65 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情

前言

OpenCV highgui 模块包含了一组丰富的函数,可用于与图像进行交互。使用这些函数,应用程序可以对鼠标或按键事件做出响应。

使用鼠标点击图片

当鼠标位于所创建的图像窗口上时,通过定义回调函数,可以对鼠标进行编程以执行特定操作。回调函数是没有显式调用的函数,但它会被应用程序调用以响应特定事件(例如鼠标与图像窗口交互的事件)。为了被应用程序识别,回调函数需要有一个特定的签名并且必须被注册。在鼠标事件处理程序的情况下,回调函数必须具有以下签名:

void onMouse(int event, int x, int y, int flags, void* param);

第一个参数 event 是一个整数,用于指定哪种类型的鼠标事件触发了对回调函数的调用。另外两个参数 xy 是事件发生时鼠标位置的像素坐标。最后一个参数用于以指向对象的指针的形式向函数发送一个额外的参数。可以通过以下方式在应用程序中注册此回调函数:

cv::setMouseCallback("Original Image", onMouse, reinterpret_cast<void*>(&image));

其中,onMouse 函数与名为 Original Image 的图像窗口相关联,并且需要图像的地址作为额外参数传递给该函数。如果我们定义如下代码所示的 onMouse 回调函数,那么每次点击鼠标时,都会在控制台上显示相应像素的值(假设图像是灰度图像) :

void onMouse(int event, int x, int y, int flags, void* param){
    cv::Mat *im = reinterpret_cast<cv::Mat*>(param);
    switch (event){
        case cv::EVENT_LBUTTONDOWN:
            // 打印坐标为 (x, y) 处的像素坐标
            std::cout << "at (" << x << "," << y << ") value is: " << static_cast<int>(im->at<uchar>(cv::Point(x, y))) << std::endl;
            break;
    }
}

为了获得 (x,y) 处的像素值,我们使用了 cv::Mat 对象的 at 方法。鼠标事件回调函数可以接收的其他事件包括 cv::EVENT_MOUSE_MOVEcv::EVENT_LBUTTONUPcv::EVENT_RBUTTONDOWNcv::EVENT_RBUTTONUP 等。

完整代码 (mouse_event.cpp) 如下所示:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

void onMouse(int event, int x, int y, int flags, void* param){
    cv::Mat *im = reinterpret_cast<cv::Mat*>(param);
    switch (event){
        case cv::EVENT_LBUTTONDOWN:
            // 打印坐标为 (x, y) 处的像素坐标
            std::cout << "at (" << x << "," << y << ") value is: " << static_cast<int>(im->at<uchar>(cv::Point(x, y))) << std::endl;
            break;
    }
}

int main() {
    cv::Mat image; // 异常处理
    std::cout << "This image is " << image.rows << " x "
              << image.cols << std::endl;

    // 将输入图像读取为灰度图像
    image=  cv::imread("1.png", cv::IMREAD_GRAYSCALE);

    if (image.empty()) {  // error handling
        std::cout << "Error reading image..." << std::endl;
        return 0;
    }
    std::cout << "This image is " << image.rows << " x " << image.cols << std::endl;
    std::cout << "This image has " << image.channels() << " channel(s)" << std::endl;

    // 创建窗口,显示图像
    cv::namedWindow("Original Image");
    cv::imshow("Original Image", image);
    // 为图像设置鼠标回调函数
    cv::setMouseCallback("Original Image", onMouse, reinterpret_cast<void*>(&image));
    cv::waitKey(0); // 等待键盘事件
    return 0;
}

编译并执行程序,结果如下所示:

$ g++ mouse_event.cpp -o mouse_event `pkg-config --cflags --libs opencv`
$ ./mouse_event

F3.png