directory

    • Some thoughts about tuning parameters
    • Analyze some angles of the image
    • Area, perimeter, rectangularity, roundness, width to length ratio
    • Example 1: Find the round hole of the automobile wheel hub (from both contour and connected domain perspectives)
    • Example 2: Find the square object in the middle of the chip
    • Example 3: Orange object on the desktop
    • conclusion

Some thoughts about tuning parameters

Reasonable parameter Settings should be based on some known condition of the problem to be solved. Such as the length range of the line segment to be extracted, the size, size (area), shape, circumference, rectangularity, roundness and so on of the workpiece to be located.

Analyze some angles of the image

1. From the algorithm of image noise reduction, histogram enhancement, binarization, frequency analysis, image morphology, geometric information extraction, feature extraction, and other mathematical methods. Output as many results as possible. 2. Screen out the actual results from the strategy. Grasp the essential gap between needed information and distracting information.

Area, perimeter, rectangularity, roundness, width to length ratio







Do not make specific analysis here, write a note specially later.

Example 1: Find the round hole of the automobile wheel hub (from both contour and connected domain perspectives)

The original:



Analysis:

1. Obtain binary images (binarization threshold or Canny operator scanning)

2. Find the connected domain through the findContours function, and the contour is the contour of the corresponding connected domain

3. The minAreaRect function is used to obtain the minimum rectangular frame (rotatable) with the outline, and then modify the characteristics of the rectangular frame to lock the target (here we limit that the length to width ratio of the rectangular frame is near 1, and the width of the rectangular frame is greater than 10).

4. For the locked contour, draw the contour through drawContours function (pay attention to the parameter, the penultimate fill -1 is to fill the modified contour, similar to flooding fill, but the flooding fill cannot obtain contour features)

Another way to think about it:

1. Get binary image (here, inverse threshold is used to make the inner circle white)

2, the use of connectedComponentsWithStats connected domain matrix function

3. Obtain x, Y, Width,height and area product (number of pixels) of connected domain smallest enclosing Quadrangles (Bounding box) by state matrix statsMat

4, by quadrilateral conditions to restrict

Idea 1 code:

int main(a)
{
	cv::Mat srcMat = imread("D:\\opencv_picture_test\\rim.png".1);
	Mat dstMat, binMat;
	cvtColor(srcMat, dstMat, COLOR_BGR2GRAY);
	threshold(dstMat, binMat, 0.255, THRESH_OTSU);
	imshow("bin", binMat);
	// Find the connected domain with the findContours function
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(binMat, contours, RETR_LIST,CHAIN_APPROX_NONE);

	// Draw the outline and fill it inside
	for (int i = 0; i < contours.size(); i++) {
		RotatedRect rbox = minAreaRect(contours[i]);
		if (fabs(rbox.size.width * 1.0 / rbox.size.height - 1) < 0.1 && rbox.size.width > 10)
			drawContours(srcMat, contours, i, Scalar(0.255.255), - 1.8);
	}
	imshow("rim", srcMat);
	waitKey(0);
}
Copy the code

Binary graph:



Frame diagram:



Idea 2 code:

int main(a)
{
	Mat lableMat;
	Mat statsMat;
	Mat centerMat;
	Mat srcMat = imread("D: \ \ opencv_picture_test \ \ \ \ contour rim PNG".1);		// Read grayscale
	Mat dstMat;
	cvtColor(srcMat, srcMat, COLOR_BGR2GRAY);
	// Call the threshold function
	threshold(srcMat, dstMat, 120.255,THRESH_BINARY_INV);
	// Corrosion operation
	// getStructuringElement(MORPH_ELLIPSE, Size(9,9));
	//morphologyEx(dstMat,dstMat, MORPH_ERODE, element);		
	int nComp = cv::connectedComponentsWithStats(dstMat,
		lableMat,
		statsMat,
		centerMat,
		8,
		CV_32S);

	for (int i = 1; i < nComp; i++)
	{
		cout << "pixels = " << statsMat.at<int>(i, 4) < <endl;
		cout << "width = " << statsMat.at<int>(i, 2) < <endl;
		cout << "height = " << statsMat.at<int>(i, 3) < <endl;
		cout << endl;
	}

	for (int i = 1; i < nComp; i++)
	{
		Rect bndbox;
		bndbox.x = statsMat.at<int>(i, 0);
		bndbox.y = statsMat.at<int>(i, 1);
		bndbox.width = statsMat.at<int>(i, 2);
		bndbox.height = statsMat.at<int>(i, 3);
		if (fabs(bndbox.width * 1.0 / bndbox.height - 1) < 0.1 && bndbox.width > 30)
		rectangle(srcMat, bndbox, CV_RGB(255.255.255), 1.8.0);
	}
	imshow("src", srcMat);
	//imshow("dst", dstMat);
	waitKey(0);
}
Copy the code

Effect:

Example 2: Find the square object in the middle of the chip

The original:



Analysis:

1. Obtain binary images (binarization threshold or Canny operator scanning)

2. Find the connected domain through the findContours function, and the contour is the contour of the corresponding connected domain

3. The minAreaRect function is used to obtain the minimum rectangular frame (rotatable) with the outline, and then modify the characteristics of the rectangular frame to lock the target (here we limit that the length to width ratio of the rectangular frame is near 1, and the width of the rectangular frame is greater than 10).

4. Draw the locked contour by drawContours function

5. Draw the border with the coordinates of the four vertices of the smallest rectangle outside the contour

Another way to think about it:

1. Get binary image (here, inverse threshold is used to make the inner circle white)

2, the use of connectedComponentsWithStats connected domain matrix function

3. Obtain x, Y, Width,height and area product (number of pixels) of connected domain smallest enclosing Quadrangles (Bounding box) by state matrix statsMat

4, by quadrilateral conditions to restrict



Idea 1 code:

* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the practice2Rectangular box -------------------------------------*/int main(a)
{
	cv::Mat srcMat = imread("D: \ \ opencv_picture_test \ \ profiles \ \ die_on_chip PNG".1);
	Mat dstMat, binMat;
	cvtColor(srcMat, dstMat, COLOR_BGR2GRAY);
	threshold(dstMat, binMat, 0.255, THRESH_OTSU);
	imshow("bin", binMat);
	// Find the connected domain with the findContours function
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(binMat, contours, RETR_LIST, CHAIN_APPROX_NONE);

	// Draw the outline
	for (int i = 0; i < contours.size(); i++) {
		RotatedRect rbox = minAreaRect(contours[i]);
		if (fabs(rbox.size.width * 1.0 / rbox.size.height - 1) < 0.1 && rbox.size.width > 10)
		{
			drawContours(srcMat, contours, i, Scalar(0.255.255), 1.8);
			Point2f vtx[4];
			rbox.points(vtx);
			for (int j = 0; j < 4; ++j) {
				cv::line(srcMat, vtx[j], vtx[j < 3 ? j + 1 : 0], Scalar(0.0.255), 3, LINE_AA);
			}
		}
	}
	imshow("die_on_chip", srcMat);
	waitKey(0);
}
Copy the code



Idea 2 code:

* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the practice1Connected domain solution: -------------------------------------*/int main(a)
{
	Mat lableMat;
	Mat statsMat;
	Mat centerMat;
	Mat srcMat = imread("D: \ \ opencv_picture_test \ \ profiles \ \ die_on_chip PNG".1);		// Read grayscale
	Mat dstMat;
	cvtColor(srcMat, srcMat, COLOR_BGR2GRAY);
	// Call the threshold function
	threshold(srcMat, dstMat, 120.255,THRESH_BINARY);
	// Corrosion operation
	// getStructuringElement(MORPH_ELLIPSE, Size(9,9));
	//morphologyEx(dstMat,dstMat, MORPH_ERODE, element);		
	int nComp = cv::connectedComponentsWithStats(dstMat,
		lableMat,
		statsMat,
		centerMat,
		8,
		CV_32S);

	for (int i = 1; i < nComp; i++)
	{
		cout << "pixels = " << statsMat.at<int>(i, 4) < <endl;
		cout << "width = " << statsMat.at<int>(i, 2) < <endl;
		cout << "height = " << statsMat.at<int>(i, 3) < <endl;
		cout << endl;
	}

	for (int i = 1; i < nComp; i++)
	{
		Rect bndbox;
		bndbox.x = statsMat.at<int>(i, 0);
		bndbox.y = statsMat.at<int>(i, 1);
		bndbox.width = statsMat.at<int>(i, 2);
		bndbox.height = statsMat.at<int>(i, 3);
		if (fabs(bndbox.width * 1.0 / bndbox.height - 1) < 0.2 && statsMat.at<int>(i, 4) > =1200)
		rectangle(srcMat, bndbox, CV_RGB(0.255.255), 1.8.0);
	}
	imshow("src", srcMat);
	//imshow("dst", dstMat);
	waitKey(0);
}
Copy the code

Effect:

Example 3: Orange object on the desktop

Analysis: 1. RGB to HSV Figure 2. HSV channels are separated to obtain the values of three channels 3. , code:

/ / * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - [3] rectangular box -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
int main(a)
{
	cv::Mat srcMat = imread("D: \ \ opencv_picture_test \ \ \ \ contour topic1. JPG".1);
	Mat dstMat, binMat;
	cvtColor(srcMat, dstMat, COLOR_BGR2HSV);
	vector<Mat> channels;
	split(dstMat, channels);
	//namedWindow("H", WINDOW_NORMAL); //WINDOW_NORMAL allows users to freely scale Windows
	//imshow("H", channels.at(0));
	namedWindow("S", WINDOW_NORMAL);//WINDOW_NORMAL allows users to freely scale Windows
	imshow("S", channels.at(1));
	//namedWindow("V", WINDOW_NORMAL); //WINDOW_NORMAL allows users to freely scale Windows
	//imshow("V", channels.at(2));
	// Copy the image of the s-channel and process it
	Mat S_Mat;
	channels.at(1).copyTo(S_Mat);
	//namedWindow("S", WINDOW_NORMAL); //WINDOW_NORMAL allows users to freely scale Windows
	//imshow("S", S_Mat);
	threshold(S_Mat, binMat, 120.255, THRESH_BINARY);
	namedWindow("bin", WINDOW_NORMAL);//WINDOW_NORMAL allows users to freely scale Windows
	imshow("bin", binMat);
	// Find the connected domain with the findContours function
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(binMat, contours, RETR_LIST, CHAIN_APPROX_NONE);

	// Draw the outline
	for (int i = 0; i < contours.size(); i++) {
		RotatedRect rbox = minAreaRect(contours[i]);
		if (fabs(rbox.size.width * 1.0 / rbox.size.height - 1) < 0.3 && rbox.size.width > 10)
		{
			drawContours(srcMat, contours, i, Scalar(0.255.255), 1.8);
			Point2f vtx[4];
			rbox.points(vtx);
			for (int j = 0; j < 4; ++j) {
				cv::line(srcMat, vtx[j], vtx[j < 3 ? j + 1 : 0], Scalar(255.255.255), 2, LINE_AA);
			}
		}
	}
	namedWindow("topic1", WINDOW_NORMAL);//WINDOW_NORMAL allows users to freely scale Windows
	imshow("topic1", srcMat);
	waitKey(0);
	return 0;

}
Copy the code

S-channel diagram:



Binarization with S-channel:



Frame diagram:

conclusion

So far, we can frame the object in terms of both contours and connected domains. MinAreaRect function can be used to obtain the parameter value of the minimum rectangle box of the contour, including part of the contour information. Using connectedComponentsWithStats get connected domain, can obtain the connected domain information. Using this information, combined with mathematical characteristics such as rectangularity, roundness and aspect ratio, some non-conforming alternatives can be eliminated.