当前位置:网站首页>Opencv application -- jigsaw puzzle

Opencv application -- jigsaw puzzle

2022-04-23 20:59:00 csuzhucong

One , Prepare picture

You can divide it manually first , There is some key information in the middle , Some are on top , Mainly these two .

Then use the program to cut out the picture of the square first :

int main()
{
	for (int i = 1; i <= 10; i++) {
		Mat img = imread("D:/pic2/img (" + to_string(i) + ").jpg",0);
		int p = min(img.rows, img.cols);
		Mat img2 = img(Rect((img.cols - p) / 2, (img.rows - p) / 2, p, p));
		imwrite("D:/pic2/a" + to_string(i) + ".jpg",img2);
	}
	return 0;
}

Cut the top :

int main()
{
	for (int i = 1; i <= 15; i++) {
		Mat img = imread("D:/pic2/img (" + to_string(i) + ").jpg",0);
		int p = min(img.rows, img.cols);
		Mat img2 = img(Rect(0, 0, p, p));
		imwrite("D:/pic2/a" + to_string(i) + ".jpg",img2);
	}
	return 0;
}

Two , Puzzle

Let's first adjust all the small graphs to a uniform size , Then sort by brightness .

For the target image , Block by , The brightness ranking is also counted separately .

Then match according to the sorting results , Just fill the small picture to the corresponding position .

In addition to brightness matching , Before finally putting it on the big picture , Also do brightness adjustment , Adjust the overall brightness to the same as the block brightness .

struct Nodes
{
	int t;
	int id;
	bool operator<(Nodes a) const
	{
		if (t == a.t)return id < a.id;
		return t < a.t;
	}
};

int imageSum(Mat img)
{
	int s = 0;
	for (int i = 0; i < img.rows; i++)for (int j = 0; j < img.cols; j++)
		s += img.at<uchar>(i, j);
	return s;
}

int main()
{
	const int N = 9;
	const int NUM = N * N;
	const int SIZE = N * 2000;
	const int PIX = 100;
	const int R1 = SIZE / PIX;
	const int R = R1 / N * R1 / N;
	Mat imgs[NUM];
	for (int i = 1; i <= NUM; i++) {
		imgs[i - 1] = imread("D:/pic2/img (" + to_string(i) + ").jpg", 0);
		resize(imgs[i - 1], imgs[i - 1], Size(PIX, PIX));
	}
	Mat img = imread("D:/pic2/img (74).jpg", 0);
	resize(img, img, Size(SIZE, SIZE));
	Nodes node[NUM * R];
	Nodes node2[NUM * R];
	for (int i = 0; i < NUM * R; i++) {
		node[i].t = imageSum(imgs[i % NUM]);
		node[i].id = i % NUM;
		node2[i].t = imageSum(img(Rect(i % R1 * PIX, i / R1 * PIX, PIX, PIX)));
		node2[i].id = i;
	}
	sort(node, node + NUM * R);
	sort(node2, node2 + NUM * R);
	for (int i = 0; i < NUM * R; i++)
	{
		Mat image;
		imgs[node[i].id % NUM].copyTo(image);
		image *= 1.0 * node2[i].t / node[i].t;
		image.copyTo(img(Rect(node2[i].id % R1 * PIX, node2[i].id / R1 * PIX, PIX, PIX)));
	}
	//imshow("img", img);
	imwrite("D:/pic2/ans.png", img);
	cv::waitKey(0);
	return 0;
}

  Joining together the results :

( Head ) Zoom in :

 ( eyes ) Zoom in :

 

3、 ... and , Optimization idea

1, There are few pictures currently used , If there are more pictures , The effect will be better .

2, Because there are few pictures , Each picture is used many times . Currently, each picture is used the same number of times , This can be optimized , Adaptively select the number of times each picture is used , The effect should be better .

3, If you want to make it colorful , The main problem is the matching of images . Grayscale images only need to be sorted according to brightness to match , Changing to a color image is equivalent to changing from one-dimensional to three-dimensional .

版权声明
本文为[csuzhucong]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/113/202204232049172865.html