introduction
One of the most common ways of binary image analysis is Contour discovery And Profile analysis , The purpose of contour discovery is to prepare for contour analysis , After contour analysis, we can get all kinds of useful attribute information of contour .
Here's edge detection , And the difference between contour extraction ：
Edge detection is mainly used to detect the sharp change of light and dark in digital image by some means （ That is, the gradient change is relatively large ） Pixel point , Biased to changes in pixels in the image . Such as canny edge detection , The results are usually stored in edge maps of the same size and type as the source image .
Contour detection refers to the detection of object boundaries in an image , They prefer to focus on the upper semantic objects . Such as OpenCV Medium findContours() function , It gets every contour and stores it as a point vector , In addition, we also get the topological information of an image , That is, the next contour of a contour 、 The previous profile 、 Index numbers of parent and embedded profiles .
One , Discovery and drawing of contour
stay OpenCV Inside use findContours() Functions and drawContours() Function to achieve this function .
 findContours() function
void findContours( InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point() )
Parameter one ： image, The input image 、 Eight bit single channel , Binary image with black background .（ It's usually after Canny、 Laplace and other edge detection operators processed binary image ）
Parameter two ：contours, Output contour image . It's a vector , Every element of a vector is an outline . therefore , Every element of this vector is still a vector . namely ：
vector<vector<Point> > contours;
Parameter 3 ：hierarchy, Output the inheritance relationship of each contour .hierarchy It's also a vector , Length and contours equal , Each element and contours The elements of are corresponding to .hierarchy Each element of is a vector of four integers . namely ：
vector<Vec4i> hierarchy;
Parameter 4 ：mode, The method of detecting contour . There are four ways ：
 RETR_EXTERNAL： Only the outer contour is detected . Ignore the holes inside the profile .
 RETR_LIST： Detect all contours , But don't build inheritance ( contain ) Relationship .
 RETR_TREE： Detect all contours , And build all the inheritance ( contain ) Relationship .
 RETR_CCOMP： Detect all contours , But only two levels of inclusion are established .
Parameter 5 ：method, Coding information for each profile . There are also four （ The first two are often used ）
 CHAIN_APPROX_NONE： Store all the points on the contour .
 CHAIN_APPROX_SIMPLE： Only inflection points on the contour are stored .
 CHAIN_APPROX_TC89_L1,CHAIN_APPROX_TC89_KCOS Use tehChinl chain The approximate algorithm
Parameter 6 ： Point, Offset . The default is 0
Be careful ： This function treats the white area as a foreground object . therefore findContours() The function is to find a white outline on a black background .（ important ！！！）
 drawContours() function
drawContours( InputOutputArray binImg, // Output image OutputArrayOfArrays contours,// All found contour objects Int contourIdx// Outline index number ,1 Means to draw all the contours const Scalar & color,// When drawing, color int thickness,// Draw line width ,1 Represents the interior of the fill profile int lineType,// The type of wire LINE_8 InputArray hierarchy,// Topology diagram int maxlevel,// Maximum number of layers , 0 Just draw the current ,1 Represents the drawing of the current and its embedded contours Point offset = Point()// Contour displacement , Optional ）
Two , Profile analysis
After getting the outline of the image , We can do profile analysis . After contour analysis, we can get all kinds of useful attribute information of contour 、 The common ones are as follows ：

Calculate the contour area :
contourArea(contour, oriented = False) // Calculate the area of the contour Parameter description ：contour For the input single contour value ;oriented: Contour direction , The default value is false. If true, This function returns a signed area , It depends on the direction of the contour ( Clockwise or counterclockwise ). If it's the default value false, The area is returned as an absolute value . According to this feature, the position of the contour can be determined by the symbol of the area .

Calculate contour perimeter ：arcLength(）
arcLength(contour, closed) // Calculate the perimeter of the contour
Parameter description ：contour For the input single contour value ,closed Indicates whether the contour is closed （true For closure ,false For not closing ）

Calculate the geometric moment and the center distance : moments(）
Moments m = moments(contours[t]); // Get the distance of the contour // Calculate the centroid of the contour double cx = m.m10 / m.m00; double cy = m.m01 / m.m00;

The circumscribed rectangle of the outline
There are two kinds of circumscribed rectangles of contours , Here's the picture , The green one is called the circumscribed rectangle boundingRect(）, Represents a rectangle that does not consider rotation and can contain the entire contour . The blue one is called the smallest circumscribed rectangle minAreaRect(), Consider rotation
1️⃣ Outside rectangle boundingRect(）
Rect rect = boundingRect(Mat(contours[i]));// Get the outline circumscribed positive rectangle rectangle(src, rect, (0, 0, 255), 2, 8, 0);
2️⃣ Minimum circumscribed rectangle minAreaRect()
RotatedRect rect = minAreaRect(contours[i]);// Get the minimum circumscribed rectangle of the contour Point2f P[4]; rect.points(P);// Get the four vertex coordinates for (int j = 0; j <= 3; j++) { line(src, P[j], P[(j + 1) % 4], Scalar(0,0,255), 1);// Connect in turn }

The smallest circumscribed circle / Fitting circle ：minEnclosingCircle(）
void minEnclosingCircle(InputArray points, Point2f& center, float& radius); points, Input twodimensional point set , It can be vector or Mat type . center, The output center of a circle . radius, The output radius of the circle . for example ： findContours(bin_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); // Look for the smallest circle of the outline of the package vector<Point2f>centers(contours.size());// The number of centers of a circle vector<float>radius(contours.size());// The number of radii for (int i = 0; i < contours.size(); i++)
{ // Find and draw the smallest circle minEnclosingCircle(contours[i], centers[i], radius[i]); circle(src, centers[i], radius[i], scalar(0,0,255), 2); }
 Fit ellipse ：fitEllipse(）
RotatedRect fitEllipse(InputArray points); // The only parameter is the input twodimensional point set , It can be vector or Mat type . for example ：
// Find and draw the smallest ellipse rota_rect[i] = fitEllipse(contours[i]); ellipse(dst, rota_rect[i], scalar(0,0,255), 2);

The convex hull of the contour ：convexHull(）
convexHull ( InputArray points, / Input twodimensional point set ,Mat Type data OutputArray hull, // Output parameters , Used to output the convex hull found bool clockwise = false, // Operation direction , When the identifier is true , The output convex hull is clockwise , Otherwise it's counter clockwise . bool returnPoints = true // Operation identifier , The default value is true, At this point, return to each point of each convex hull , Otherwise, it returns the exponent of each point of the convex hull )

Polygonal approximation  Close to the real shape ：approxPolyDP(）
void approxPolyDP( InputArray curve, // Input curve , Generally, it is a set of points composed of contour points of an image OutputArray approxCurve, // Represents the output polygon point set double epsilon, // Mainly refers to the accuracy of the output , Is the maximum distance between the other contour points bool closed // Indicates whether the output polygon is closed )