该代码主要根据https://blog.csdn.net/yph001/article/details/79836960这篇上面的进行了微调。
主要目的是输入一张图片,在图像中,用鼠标画矩形框选中感兴趣的区域,然后保存框选的感兴趣区域同时,输出感兴趣区域的图像在原图中的左上角点的坐标以及框选的图像的宽和高。代码具体如下:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
/*
读取一张图片,然后画框
画完之后按esc即可退出画框
同时输出img和坐标
*/
using namespace cv;
using namespace std;
cv::Mat img;
bool select_flag = false;
cv::Rect m_select;
cv::Point origin;
int ROI_count;
void onMouseRectPicking(int event, int x, int y, int, void*)
{
if (select_flag)
{
//不一定要等鼠标弹起才计算矩形框,而应该在鼠标按下开始到弹起这段时间实时计算所选矩形框
m_select.x = MIN(origin.x, x);
m_select.y = MIN(origin.y, y);
//算矩形宽度和高度
m_select.width = abs(x - origin.x);
m_select.height = abs(y - origin.y);
//保证所选矩形框在视频显示区域之内
m_select &= cv::Rect(0, 0, img.cols, img.rows);
}
if (event == CV_EVENT_LBUTTONDOWN)
{
//鼠标按下的标志赋真值
select_flag = true;
//保存下来单击捕捉到的点
origin = cv::Point(x, y);
//这里一定要初始化,宽和高为(0,0)是因为在opencv中Rect矩形框类内的点是包含左上角那个点的,但是不含右下角那个点
m_select = cv::Rect(x, y, 0, 0);
}
else if (event == CV_EVENT_LBUTTONUP)
{
select_flag = false;
ROI_count++;
}
}
int main(int argc, char* argv[])
{
bool stop = false;
cv::namedWindow("capframe", CV_WINDOW_AUTOSIZE);
cv::setMouseCallback("capframe", onMouseRectPicking, 0);
char pic_name[40];
ROI_count = 0;
//用于存储框选的图像和rect
Rect rect;
Mat ROI;
while (!stop)
{
img = imread("自动化院照严肃版.jpg");
cv::rectangle(img, m_select, cv::Scalar(255, 0, 0), 2, 8, 0); // 画矩形框
cv::imshow("capframe", img);
if ((m_select.x != 0) && (m_select.y != 0) && (m_select.width != 0) && (m_select.height != 0))
{
sprintf_s(pic_name, "ROI_%d.jpg", ROI_count);
ROI_count++;
ROI = img(m_select);
rect=m_select;
}
char key = cv::waitKey(30);
if (key == 27)
stop = true;
}
//显示框选的图像
imshow("ROI_WIN", ROI);
imwrite(pic_name, ROI);
//输出框选的图像在原图中左上角点的坐标以及框选图像的宽高
cout << rect.x << endl;
cout << rect.y << endl;
cout << rect.width << endl;
cout << rect.height << endl;
waitKey(0);
return 0;
}