OpenCV图像处理——深度学习样本制造

前言

在做深度学习相关的项目时,往往最麻烦的是样本的收集,或者只有很少的一些样本,训练根本达不到想要的效果,很多网络模型的配置文件里面都有样本增强的定义,是对样本做旋转,变换之类的操作,但没有给样本加一些背景来制造增强样本的数量。

一、样本准备

1.我做一个发票检测位置到识别里面文字的项目,但我手里并没有多少张发票样本,在网上也很难找到能用的样本,我的应用场景是把发票放在桌面上拍照之后,检测识别。所以我先去网上下一些木纹桌面的样本,放在一个目录,完成之后从0开始命名如下:在这里插入图片描述
2.我自己手中有发票样本也放在一个目录,也从0开始命名如下:
OpenCV图像处理——深度学习样本制造_第1张图片

二、代码

1.代码用到OpenCV的基本库,读写文件就随便写了个循环读写,最好是改成boost库来读写文件。
2.代码的思想,大概是要的发票样本按任意角度旋转,再与背景图像融合。
3.代码:

bool ROI_AddImage(Mat &cv_back, Mat &cv_front, Mat &cv_dst)
{
	Mat cv_mask = cv_front.clone();
	if (!cv_back.data)
	{
		std::cout << "读入图片失败" << std::endl;
		return false;
	}
	if (!cv_front.data)
	{
		std::cout << "读入图片失败" << std::endl;
		return false;
	}

	int w = (cv_back.cols - cv_front.cols) / 2;
	int h = (cv_back.rows - cv_front.rows) / 2;
	Mat imageROI = cv_back(Rect(w, h, cv_front.cols, cv_front.rows));

	Mat mask;

	cv::cvtColor(cv_mask, mask, COLOR_BGR2GRAY);
	
	cv_front.copyTo(imageROI, mask);  
	
	cv_dst = cv_back.clone();
}

int main()
{
	string back = "C:/Users/matt/Desktop/8/";
	string front = "C:/Users/matt/Desktop/80/";
	string save = "C:/Users/matt/Desktop/data/";

	for (int i = 0; i < 20; i++)
	{
		string back_name = back + to_string(i) + ".jpg";
		string front_name = front + to_string(i) + ".jpg";

		Mat back = imread(back_name);
		Mat cv_front = imread(front_name);
		
		for (int j = 0; j < 5; j++)
		{
			Mat cv_back = back.clone();
			Mat cv_rotata;
			int a = rand() % 180;
			rotateImage2(cv_front, cv_rotata, a, 0);
			Mat cv_png;
			toPng(cv_rotata, cv_png, 0);
		
			if (cv_png.rows > cv_back.rows)
			{
				resize(cv_back, cv_back, cv_png.size(), 0.0, 0.0, INTER_NEAREST);
				resize(cv_png, cv_png, Size(cv_png.cols / 1.2, cv_png.rows / 1.2));
			}
			if (cv_png.rows < cv_back.rows)
			{
				resize(cv_png, cv_png, cv_back.size(), 0.0, 0.0, INTER_NEAREST);
				resize(cv_png, cv_png, Size(cv_png.cols / 1.2, cv_png.rows / 1.2));
			}

			Mat cv_dst;
			ROI_AddImage(cv_back, cv_png, cv_dst);
			string save_name = save + to_string(i) + to_string(j) + ".jpg";
			imwrite(save_name, cv_dst);
		}
	}
	
	waitKey(0);
	return 0;
}

void toPng(cv::Mat &src, cv::Mat &dst, int mark)
{
	cv::Mat cv_input = src.clone();
	if (cv_input.channels() != 4)
	{
		cv::cvtColor(cv_input, dst, CV_BGR2BGRA);
	}
	else
	{
		return;
	}
	for (int y = 0; y < dst.rows; ++y)
	{
		for (int x = 0; x < dst.cols; ++x)
		{
			cv::Vec4b & pixel = dst.at<cv::Vec4b>(y, x);
			if (pixel[0] == mark && pixel[1] == mark && pixel[2] == mark)
			{
				pixel[3] = 0;
			}
		}
	}
}

int rotateImage(Mat &img, Mat & imgout, int degree, int border_value)
{
	if (img.empty())
		return 1;
	degree = -degree;
	double angle = degree  * CV_PI / 180.; // 弧度  
	double a = sin(angle), b = cos(angle);
	int width = img.cols;
	int height = img.rows;
	int width_rotate = int(width * fabs(b) + height * fabs(a));
	int height_rotate = int(height * fabs(b) + width * fabs(a));
	if (width_rotate <= 20 || height_rotate <= 20)
	{
		width_rotate = 20;
		height_rotate = 20;
	}

	float map[6];
	Mat map_matrix = Mat(2, 3, CV_32F, map);
	// 旋转中心
	CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2);
	CvMat map_matrix2 = map_matrix;
	cv2DRotationMatrix(center, degree, 1.0, &map_matrix2);//计算二维旋转的仿射变换矩阵
	map[2] += (width_rotate - width) / 2;
	map[5] += (height_rotate - height) / 2;
	int chnnel = img.channels();
	if (chnnel == 3)
		warpAffine(img, imgout, map_matrix, Size(width_rotate, height_rotate), 1, 0, Scalar(0, 0, 0));
	else
		warpAffine(img, imgout, map_matrix, Size(width_rotate, height_rotate), 1, 0, 255);
	return 0;
}

4.可以自己设置融合多少次,运行之后的结果如下:

注:有兴趣于图像处理学习的可以加
OpenCV图像处理——深度学习样本制造_第2张图片

你可能感兴趣的:(opencv)