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.