opencv cpp实现鼠标框选区域并显示选择的图片区域

⌚Time: 2023-09-15 14:22:27

👨‍💻Author: Jack Ge

OpenCV可以使用setMouseCallback设置鼠标事件的回调函数,从而然后根据需要进行处理。

setMouseCallback原型为:


void cv::setMouseCallback(const cv::String& windowName, MouseCallback onMouse, void* userData = 0);

其中,参数说明如下:



windowName:窗口名称

onMouse:回调函数的指针,用于处理鼠标事件

userData:用户数据指针,可以传递给回调函数

鼠标事件包括:



CV_EVENT_MOUSEMOVE:鼠标移动事件

CV_EVENT_LBUTTONDOWN:鼠标左键按下事件

CV_EVENT_LBUTTONUP:鼠标左键释放事件

CV_EVENT_RBUTTONDOWN:鼠标右键按下事件

CV_EVENT_RBUTTONUP:鼠标右键释放事件

CV_EVENT_MBUTTONDOWN:鼠标中键按下事件

CV_EVENT_MBUTTONUP:鼠标中键释放事件



回调函数的原型为:

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

其中,

event:鼠标事件类型

x、y:鼠标事件发生的位置

flags:鼠标事件的附加信息

userdata:用户数据指针

onMouse() 函数是一种回调函数,它将在用户与窗口交互时被调用。例如,当用户在窗口中单击鼠标时,这个函数将被调用。用户可以根据需要在这个函数中编写代码来响应鼠标事件。


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

event:表示鼠标事件的类型,可以是

CV_EVENT_MOUSEMOVE(鼠标移动)、CV_EVENT_LBUTTONUP(左键释放)、CV_EVENT_LBUTTONDOWN(左键按下)、CV_EVENT_RBUTTONUP(右键释放)、CV_EVENT_RBUTTONDOWN(右键按下)等。

x 和 y:表示鼠标事件在窗口中的坐标。

flags:表示鼠标的标志位,可以是

CV_EVENT_FLAG_LBUTTON(左键被按下)、CV_EVENT_FLAG_RBUTTON(右键被按下)、CV_EVENT_FLAG_MBUTTON(中键被按下)等。

userdata:表示用户自定义的数据,可以是任何类型的指针。

代码

ROI.cpp




#include <opencv2/opencv.hpp>

#include <stdio.h>

 

using namespace cv;

 

Mat src, temp;

void on_mouse(int event, int x, int y, int flags, void *userData)

{

    static Point prePoint(0, 0);//初始坐标,设为static类型所以下次可以读取

    static Point curPoint(0, 0);//实时坐标,设为static类型所以下次可以读取



    src.copyTo(temp);//拷贝原图到缓存图像

    if (event == CV_EVENT_LBUTTONDOWN)//左键按下,储存初始坐标

    {

        prePoint = Point(x, y);

    }

    if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))//鼠标移动时

    {



    }

    else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))//鼠标按下左键并移动时,显示拖拽框



    {

        curPoint = Point(x, y);//储存当前鼠标坐标

        rectangle(temp, prePoint, curPoint, Scalar(0, 255, 0), 2, 8, false);//实时绘制鼠标左键拖动时形成的矩形 

        imshow("img", temp);//显示绘制的图像

    }

    if (event == CV_EVENT_LBUTTONUP)//左键抬起

    {

        curPoint = Point(x, y);//储存当前鼠标坐标

        //画坐标信息

        char info[16] = {0};

        sprintf(info,"(%d %d)",prePoint.x,prePoint.y);

        putText(temp, info, prePoint, FONT_HERSHEY_SIMPLEX, 0.6, Scalar(0, 0, 255), 1, 8, false);//把表示鼠标左键按下时坐标的文字写到图像temp上

        sprintf(info,"(%d %d)",curPoint.x,curPoint.y);

        putText(temp, info, curPoint, FONT_HERSHEY_SIMPLEX, 0.6, Scalar(0, 0, 255), 1, 8, false);//把表示鼠标左键按下时坐标的文字写到图像temp上

        //画拖拽框

        rectangle(temp, prePoint, curPoint, Scalar(0, 255, 0), 2, 8, false);//根据初始点和结束点,将矩形画到temp上 

        //显示图片

        imshow("img", temp);



        //独立opencv窗口显示截取的图像

        int width = abs(prePoint.x - curPoint.x);

        int height = abs(prePoint.y - curPoint.y);

        if (width == 0 || height == 0)//排除只点一下鼠标左键而没有进行拖曳操作的情况

        {

            ;

        }else{

            Mat res = src(Rect(min(curPoint.x, prePoint.x), min(curPoint.y, prePoint.y), width, height));

            destroyWindow("result");//避免上一次截取图像的显示对这一次截取图像的显示的影响

            namedWindow("result");

            imshow("result", res);

            waitKey(0);

        }

    }

}

int main()

{

    src = imread("D:\\z.jpg");

    namedWindow("img");

    imshow("img", src);

    setMouseCallback("img", on_mouse, 0);//设置窗口鼠标事件回调函数

    cv::waitKey(0);

    return 0;

}