1.目的
读取一张图片,在该图片上截取一个ROI区域,将截取的图像在新窗口显示,并可以保存至工程目录下。
2.实现环境
C++、VS2017、opencv
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("截图");
}
完整项目链接