版权声明:转载需标明该文链接。 https://blog.csdn.net/zaibeijixing/article/details/83176330
版权声明:原创文章,转载需标明该文链接。 https://blog.csdn.net/zaibeijixing/article/details/83176330
由于项目需要,需要鼠标在图像上画矩形框,保留矩形框信息。再调用矩形框信息,显示到另一幅图像上。
查找资料,尝试对比,写了两个程序,当然两个程序也可以根据需要合并。
①图像窗口鼠标取矩形框保存到文本
代码如下:
//第一篇:在图像上鼠标标记矩形框,保存矩形信息到文本txt。
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <fstream>
#include <vector>
using namespace cv;
using namespace std;
cv::Mat org, dst, img, tmp;
vector<Rect> captureRects;
void on_mouse(int event, int x, int y, int flags, void *ustc) //event鼠标事件代号,x,y鼠标坐标,flags拖拽和键盘操作的代号
{
static Point pre_pt = { -1, -1 }; //初始坐标
static Point cur_pt = { -1, -1 }; //实时坐标
char temp[16];
if (event == CV_EVENT_LBUTTONDOWN) //左键按下,读取初始坐标,并在图像上该点处划圆
{
org.copyTo(img);//将原始图片复制到img中
sprintf_s(temp, "(%d,%d)", x, y);
pre_pt = Point(x, y);
putText(img, temp, pre_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);//在窗口上显示坐标
circle(img, pre_pt, 3, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);//划圆
imshow("img", img);
}
else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON)) //左键没有按下的情况下鼠标移动的处理函数
{
img.copyTo(tmp);//将img复制到临时图像tmp上,用于显示实时坐标
sprintf_s(temp, "(%d,%d)", x, y);
cur_pt = Point(x, y);
putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));//只是实时显示鼠标移动的坐标
imshow("img", tmp);
}
else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON)) //左键按下时,鼠标移动,则在图像上划矩形
{
img.copyTo(tmp);
sprintf_s(temp, "(%d,%d)", x, y);
cur_pt = Point(x, y);
putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
rectangle(tmp, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 2, 8, 0);//在临时图像上实时显示鼠标拖动时形成的矩形
imshow("img", tmp);
}
else if (event == CV_EVENT_LBUTTONUP) //左键松开,将在图像上划矩形
{
org.copyTo(img);
sprintf_s(temp, "(%d,%d)", x, y);
cur_pt = Point(x, y);
putText(img, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
circle(img, pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
rectangle(img, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 5, 8, 0);//根据初始点和结束点,将矩形画到img上
imshow("img", img);
img.copyTo(tmp);
//截取矩形包围的图像,并保存到dst中
int width = abs(pre_pt.x - cur_pt.x);
int height = abs(pre_pt.y - cur_pt.y);
if (width == 0 || height == 0)
{
printf("width == 0 || height == 0");
return;
}
/* _____________________________ 记录数据、保存文件,把矩形信息保到vector __________________________________ */
Rect draw_rect = { min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height };;
captureRects.push_back(draw_rect);
dst = org(draw_rect);
namedWindow("dst");
imshow("dst", dst);
waitKey(0);
}
}
// 具体操作步骤:可以先拉伸压缩窗口,点击鼠标从左上往右下画矩形框,所有矩形画好后,先关闭大图,再关闭小图,ok了。先关哪个都行。
int main()
{
org = imread("AOI_ROI.jpg");
org.copyTo(img);
org.copyTo(tmp);
namedWindow("img", 0); //定义一个img窗口
setMouseCallback("img", on_mouse, 0); //调用回调函数
imshow("img", img);
waitKey(0);// 【这句话,必须加上,否则直接跳到最后不执行写操作】
cout << captureRects.size() << "hyj" << endl;
ofstream file("sample.txt");
if (!file)
{
cout << "open file error!";
return 1;
}
vector<Rect>::iterator it = captureRects.begin();
cout << "01" << endl;
for (; it != captureRects.end(); ++it)
{
// 好像是直接跳过文件这一块。
cout << it->x << ' ' << it->y << ' ' << it->width << ' ' << it->height << endl;
file << it->x << ' ' << it->y << ' ' << it->width << ' ' << it->height << endl;
}
cout << "02" << endl;
file << endl;
cout << "03" << endl;
file.close();
cout << "ok" << endl;
cv::waitKey(0);
return 0;
}
②将文本中的矩形框信息显示到图像中
代码如下:
//第二篇:读取文本,把矩形画到图像上。
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <fstream>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
Mat img(4200, 4200, CV_8UC3, Scalar(255, 255, 255)); //创建空白图像以画框
namedWindow("img", 0); imshow("img", img);
FILE *fp;
fopen_s(&fp, "sample.txt", "r");
int i;
Rect rect[10];
for (i = 0; i < 11; i++)
{
fscanf_s(fp, "%d %d %d %d", &rect[i].x, &rect[i].y, &rect[i].width, &rect[i].height); //读取文件中的数据,遇到空格和换行停止读。
printf_s("%d %d %d %d\t", rect[i].x, rect[i].y, rect[i].width, rect[i].height); //将文件打印出来。
printf("\n");
}
fclose(fp);
for (i = 0; i < 4; i++)
rectangle(img, rect[i], Scalar(255, 0, 0), 10);
namedWindow("img", 0); imshow("img", img);
waitKey();
getchar();
}
以上都为成功运行的代码,主要参考见:
DoubleLi 《opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像》https://www.cnblogs.com/lidabo/p/3437587.html
https://zhidao.baidu.com/question/455048909019613205.html 作者百度号:chengkun183
③附上另一个直接参考的代码,保存四个鼠标点到文件
//第三篇//四个鼠标点,写文件
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <fstream>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;
using namespace cv;
Mat org;
int n = 0;
vector<Point> capturePoint;
void on_mouse(int event, int x, int y, int flags, void *ustc)//event鼠标事件代号,x,y鼠标坐标,flags拖拽和键盘操作的代号
{
Point pt;//坐标点;
char coordinateName[16];
if (event == CV_EVENT_LBUTTONDOWN)//左键按下,读取坐标,并在图像上该点处划圆
{
pt = Point(x, y);
//cout << x << " " << y << endl;
capturePoint.push_back(pt);
//cout << capturePoint[n].x << " " << capturePoint[n].y << endl;
//cout << "n=" << n << endl;
n++;
circle(org, pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);//划圆
sprintf_s(coordinateName, "(%d,%d)", x, y);
putText(org, coordinateName, pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);//在窗口上显示坐标
if (n >= 4)
{
imshow("org", org);
cvDestroyAllWindows();
}
}
}
int main()
{
org = imread("E:/mypic/0.jpg", 1);
namedWindow("org", 1);//定义一个org窗口
setMouseCallback("org", on_mouse, 0);//调用回调函数
imshow("org", org);
waitKey(0);//移动到这里执行,试一下
cout << n << endl;
cout << capturePoint.size() << endl;
ofstream file("sample.txt");
if (!file)
{
cout << "open file error!";
return 1;
}
vector<Point>::iterator it = capturePoint.begin();
for (; it != capturePoint.end(); ++it)
{
file << it->x << ',' << it->y << endl;
}
file << endl;
file.close();
// waitKey(0);移动到imshow("org",org);的下面一行执行
return 0;
}