opencv ①图像窗口鼠标取矩形框保存到文本,②将文本中的矩形框信息显示到图像中

版权声明:转载需标明该文链接。 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;
}

完结。

版权声明:原创文章,转载需标明该文链接。 https://blog.csdn.net/zaibeijixing/article/details/83176330

猜你喜欢

转载自blog.csdn.net/zaibeijixing/article/details/83176330