Opencv鼠标回调函数[SetMouseCallBack]

#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

Mat img;
void onMouse(int event, int x, int y, int flags, void* param)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        cout << "Mouse Down" << endl;
        circle(img, Point(x, y), 50, Scalar(0, 0, 0), 2, 8);
    }
}

int main()
{
    //=================================================读图
    /*Mat src = imread("C:\\Users\\DELL\\Desktop\\膀胱癌细胞识别完善\\运行示例6.png");
    int height = src.rows;
    int width = src.cols;
    cout << "图像的宽:" << width << endl << "图像高:" << height << endl;
    imshow("opencv test", src);
    waitKey(0);
    destroyAllWindows();*/
    //=================================================读取视频
    /*Mat frame;
    VideoCapture cap;
    cap.open(0);
    if (cap.isOpened())
    {
        namedWindow("video", WINDOW_NORMAL);
        while (cap.grab())
        {
            cap.read(frame);
            imshow("video", frame);
            if (waitKey(20) > 0)
                break;
        }
       
    }
    waitKey(0);
    cap.release();
    destroyAllWindows();*/
    //========================================================画线画矩形以及写字
    //Mat img = Mat(300, 300, CV_8UC3, Scalar(0, 0, 0));
    //line(img, Point(20, 20), Point(200, 200), Scalar(0, 255, 255),2,8);
    //circle(img, Point(150, 150), 100, Scalar(255, 0, 0), 2, 8);
    //rectangle(img, Point(20, 20), Point(200, 200), Scalar(255, 255, 255), 2, 8);    //若线宽设置为 -1 ,则为填充
    //putText(img, "Open CV", Point(150, 150), FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 255, 0), 1, 8);
    //namedWindow("img", WINDOW_NORMAL);
    //imshow("img", img);
    //waitKey(0);
    //destroyAllWindows();


    //============================================================鼠标回调事件
    img = Mat(500, 500, CV_8UC3, Scalar(255, 255, 255));
    namedWindow("Mouse", WINDOW_NORMAL);
    setMouseCallback("Mouse",onMouse,&img);
    while (1)
    {
        imshow("Mouse", img);
        if (27 == waitKey(20))
        {
            break;     //20ms刷新一次显示,如果按下Esc则退出循环
        }
    }
    destroyAllWindows();

}

1.目的
读取一张图片,在该图片上截取一个ROI区域,将截取的图像在新窗口显示,并可以保存至工程目录下。
2.实现环境
C++、VS2019、opencv4.3.0
3.回调函数原理
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
4.实现代码如下:

#include <opencv2/opencv.hpp>
#include <Windows.h>
using namespace cv;
 
#define WINDOW "程序窗口"
 
void on_MouseHandle(int event, int x, int y, int flags, void*param);
void DrawRectangle(Mat& _img, Rect& _box);
void shotScreen(Mat& _img);
 
Rect g_rectangle;//截图位置信息
bool g_drawingBox = false;//绘图标识
Mat srcROI;//截图
 
int main()
{
	g_rectangle = Rect(-1, -1, 0, 0);
	Mat srcImg, tempImg;
	srcImg = imread("../Leana.png");//读取图片
	srcImg.copyTo(tempImg);
 
	namedWindow(WINDOW);//定义一个窗口
	setMouseCallback(WINDOW, on_MouseHandle, (void*)&srcImg);//对WINDOW窗口进行鼠标检测
 
	//不断更新
	while (1)
	{
		srcImg.copyTo(tempImg);
		if (g_drawingBox)
			DrawRectangle(tempImg, g_rectangle);//画出矩形g_rectangle
		imshow(WINDOW, tempImg);
		if (waitKey(10) == 27)//按下esc结束
			break;
	}
	return 0;
}
 
//event:鼠标事件标志(不需要自己传参)
//x:鼠标在窗口中的x坐标
//y:鼠标在窗口中的y坐标
//flags:自定义的宏,做标记符,Ture时开始绘制矩形,false时不绘制
//* param:传入的图像
void on_MouseHandle(int event, int x, int y, int flags, void*param)
{
	Mat& img = *(Mat*)param;
	switch (event)//检测鼠标事件
	{
	case EVENT_MOUSEMOVE://鼠标移动事件
	{
		if (g_drawingBox)//如果鼠标左键按下,则计算当前位置g_rectangle的宽高
		{
			g_rectangle.width = x - g_rectangle.x;
			g_rectangle.height = y - g_rectangle.y;
		}
	}
	break;
	case EVENT_LBUTTONDOWN://鼠标左键按下事件
	{
		g_drawingBox = true;//将绘图标识设为真,准备绘图
		g_rectangle = Rect(x, y, 0, 0);//保存起点
	}
	break;
	case EVENT_LBUTTONUP://鼠标左键抬起事件
	{
		g_drawingBox = false;//将绘图标识设为假,停止绘图
		//处理截图区域(因为向上截取则宽高为负,需要转换成正值)
		if (g_rectangle.width < 0)
		{
			g_rectangle.x += g_rectangle.width;
			g_rectangle.width *= (-1);
		}
		if (g_rectangle.height < 0)
		{
			g_rectangle.y += g_rectangle.height;
			g_rectangle.height *= (-1);
		}
		//若截图区域面积为0,则不进行截图
		if (g_rectangle.width != 0 || g_rectangle.height != 0)
		{
			srcROI = img(g_rectangle);
			shotScreen(srcROI);
		}
	}
	break;
	}
}
 
void DrawRectangle(Mat& _img, Rect& _box)
{
	rectangle(_img, _box.tl(), _box.br(), Scalar(0, 0, 255));
}
 
//_img:截取的图片
void shotScreen(Mat& _img)
{
	imshow("截图", _img);
	UINT ret = MessageBox(NULL, "是否保存当前截图", "提示", MB_YESNO);
	if (ret == IDYES)
		imwrite("../截图.png", _img);
	else
		destroyWindow("截图");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NCUTer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值