OpenCV圖像處理——深度學習樣本製造

前言

在做深度學習相關的項目時,往往最麻煩的是樣本的收集,或者只有很少的一些樣本,訓練根本達不到想要的效果,很多網絡模型的配置文件裏面都有樣本增強的定義,是對樣本做旋轉,變換之類的操作,但沒有給樣本加一些背景來製造增強樣本的數量。

一、樣本準備

1.我做一個發票檢測位置到識別裏面文字的項目,但我手裏並沒有多少張發票樣本,在網上也很難找到能用的樣本,我的應用場景是把發票放在桌面上拍照之後,檢測識別。所以我先去網上下一些木紋桌面的樣本,放在一個目錄,完成之後從0開始命名如下:在這裏插入圖片描述
2.我自己手中有發票樣本也放在一個目錄,也從0開始命名如下:
在這裏插入圖片描述

二、代碼

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.可以自己設置融合多少次,運行之後的結果如下:
在這裏插入圖片描述

注:有興趣於圖像處理學習的可以加
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章