OpenCV realizes the connection of adjacent regions in the image and merges them

Description of the problem:
When performing image segmentation, due to the unsatisfactory segmentation effect, there is an unsegmented situation between two adjacent regions. If you use the method of merging boundingBox to deal with it, it will inevitably introduce more irrelevant areas, which will increase the difficulty of segmentation. Therefore, this paper considers connecting the two regions and looking for the convex hull after connection, so as to realize the merging of adjacent regions for subsequent processing.
insert image description here

Figure 1 The original image and its boundingBox

Algorithm idea:
extract contours -> calculate the distance between the contours -> connect two contours smaller than the threshold T -> find the convex hull and fill it
insert image description here

Figure 2 Connecting adjacent regions (blue lines) and corresponding convex hulls

It is obvious from Figure 2 that this method reduces the irrelevant area compared to the way of merging boundingBox.

The complete implementation code is as follows:

vector<Point> GetPoint(vector<Point> contour)
{
    
    
	cv::Rect rect = cv::boundingRect(cv::Mat(contour));
	Point up, down, left, right;
	up.x = rect.x + rect.width / 2;
	up.y = rect.y;
	vector<Point> p1;
	p1.push_back(up);
	down.x = rect.x + rect.width / 2;
	down.y = rect.y + rect.height;
	p1.push_back(down);
	left.x = rect.x;
	left.y = rect.y + rect.height / 2;
	p1.push_back(left);
	right.x = rect.x + rect.width;
	right.y = rect.y + rect.height / 2;
	p1.push_back(right);
	return p1;
}
void ConnectNearRegion()
{
    
    
	Mat src = imread("D:\\PyProject01\\images\\metal.png");
	Mat gray, imageBw;
	cvtColor(src, gray, CV_BGR2GRAY);
	threshold(gray, imageBw, 0, 255, CV_THRESH_BINARY);
	//腐蚀
	/*cv::Mat element = cv::getStructuringElement(MORPH_RECT, Size(3, 3));
	Mat metalMask;
	cv::erode(imageBw, metalMask, element);*/
	vector<vector<Point>> boundingPoints;
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(imageBw, contours, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
	//每个轮廓都只提取四个点
	for (int i = 0; i < contours.size(); ++i)
	{
    
    
		vector<Point> p1 = GetPoint(contours[i]);
		boundingPoints.push_back(p1);
	}
	//计算轮廓间的距离
	for (int i = 0; i < contours.size(); ++i)
	{
    
    
		cv::Rect rect = cv::boundingRect(cv::Mat(contours[i]));
		//rectangle(imageBw, rect, Scalar(200,0,255), 1);
		vector<Point> p1 = contours[i]; // boundingPoints[i];
		for (int i1 = i+1; i1 < contours.size(); ++i1)
		{
    
    
			vector<Point> p2 = contours[i1];// boundingPoints[i1];
			//分别求p1和p2的四个点距离
			float T = 10;
			int flag = 0;
			for (int i2 = 0; i2 < p1.size(); i2++)
			{
    
    
				for (int i3 = 0; i3 < p2.size(); i3++)
				{
    
    
					float d = sqrt(pow(float(p1[i2].x - p2[i3].x), 2) + pow(float(p1[i2].y - p2[i3].y), 2));
					if (d < T)
					{
    
    
						line(imageBw, p1[i2], p2[i3], Scalar(255, 0, 0), 1, LINE_AA, 0);
						flag = 1;
						break;
					}
				}
				if (flag)
					break;
			}
		}
	}
	imshow("", imageBw);
	waitKey();
	//find convex
	vector<vector<Point>> contours2;
	vector<Vec4i> hierarchy2;
	//find image contours
	findContours(imageBw, contours2, hierarchy2, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
	vector<vector<Point>>hull2(contours2.size());
	//get convex
	Mat filling = Mat::zeros(imageBw.size(), CV_8UC1);
	for (int i = 0; i < contours2.size(); i++)
	{
    
    
		convexHull(Mat(contours2[i]), hull2[i], false);
		fillPoly(filling, hull2[i], Scalar(255));
	}
	imshow("", filling);
	waitKey();
}

Guess you like

Origin blog.csdn.net/qq_44924694/article/details/129747440