OpenCV implements contour discovery

  • 2020-06-15 10:01:35
  • OfStack

Preface:

After we extract the target object in the image through threshold segmentation, we need to extract the contour of the target object through edge detection. Using these two methods, we can basically determine the edge or foreground of the object. Next, what we usually need to do is to fit the foreground of these edges, such as fitting out the minimum outer rectangle, circle, convex shell and other geometric shapes containing the foreground or edge pixels, so as to lay a solid foundation for calculating their areas or template matching and other operations.

1. Find and draw Outlines

First, understand the definition of 1 outline. 1 outline represents a series of points (pixels), which constitute an ordered set of points, so an outline can be understood as an ordered set of points.

1.1 findContour () function

In OpenCV, a function is provided to return or output an ordered set of points or an ordered set of points (refers to multiple ordered set of points). The function findContour calculates the contour from the 2-value image. It can use the image processed by the Canny() function because such an image contains edge pixels. You can also use images processed by threshold() or adaptiveThreshold(), whose edges are hidden at the junction of positive and negative regions. The declaration of this function is as follows:


void findContours(InputOutputArray image,OutputArrayOfArrays contours,OutputArray hierarchy,int mode,int method,Point offset = Point());

Its parameters are explained as follows:

(1) image: Single-channel image matrix, which can be a grayscale image, but is more commonly used as a 2-valued image. Generally, 1 is a 2-valued image processed by edge detection operators such as Canny and Laplace.

(2) contours: vector < vector < Point > > Type, is a vector, and is a double vector, in which each element holds a vector of a set of points composed of consecutive Point points, and each set of Point points is an outline. The vector contours has as many elements as it has Outlines.

(3) hierarchy: vector < Vec4i > Type Vec4i is Vec < int,4 > Each element in the container is a vector containing four int variables, so by definition hierarchy is also a vector containing an array of four int integers. The element in vector hiararchy and the element in contour vector contours correspond to 11 and have the same vector capacity. Four int type variables for each element in the hierarchy vector -- hierarchy[i][0] ~ i [i][3], respectively represent the index number of the last contour, the first contour, the parent contour, and the embedded contour. The corresponding bit of hierarchy[i][0] ~hierarchy[i][3] is set as the default value -1 if the current contour does not have the corresponding last contour, the first contour, the parent contour or the embedded contour.

(4) mode: int, the retrieval mode defining the contour:

Value 1: CV_RETR_EXTERNAL only detects the outermost contour, and the inner contour contained in the outer contour is ignored.

All the contours of the value 2: CV_RETR_LIST detection, including the inner and outer contour, but detect does not establish a hierarchy, the outline of independence between each other, there is no hierarchy, this means that the contour retrieval mode does not exist father or embedded outline, so hierarchy vector all elements in the third, fourth component will be set to 1, specific talk about below;

Value 3: CV_RETR_CCOMP detects all contours, but only two hierarchical relationships are established for all contours. The periphery is the top layer. If the inner contour in the periphery also contains other contour information, then all the contours in the inner circumference belong to the top layer.

Value 4: CV_RETR_TREE, detect all contours, and establish a hierarchical tree structure for all contours. The outer contour contains the inner contour, which can continue to contain the inner contour.

(5) method: int type, the approximate method to define the contour:

Value 1: CV_CHAIN_APPROX_NONE stores all continuous contour points on the object boundary into the contours vector;

Value 2: CV_CHAIN_APPROX_SIMPLE only saves the inflexion point information of the contour, saves all the points at the inflexion point into the contours vector, and does not retain the information points on the line segment between the inflexion point and the inflexion point.

Value 3 and 4: CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS use teh-ES122en chain approximation algorithm;

(6) Point: Offset, the offset of all contour information relative to the corresponding point of the original image, equivalent to adding this offset to every detected contour point, and Point can also be negative value.

Notes:

Obviously, the name of the function tells you what "looking for Outlines" means. We can get the edge 2 value graph or foreground 2 value graph through the edge detection algorithm, and the edge pixel or foreground pixel of the 2 value graph can be seen to be composed of multiple contours (point sets). The function findContours is to divide the edge pixel or foreground pixel of a 2-value graph into multiple contours for separate discussion of each contour. The parameter image represents a 2-value graph and contours represents multiple contours output. For C++API of this function, vector is used for the description of 1 contour < Point > , how would multiple contours (multiple sets of points) be represented? What data structure is the parameter contours? In C++API, vector is used < vector < Point > > Describe multiple contours, that is, multiple contours stored in 1 vector.

1.2 drawContours () function

OpenCV also provides a function to draw the multiple contours found by findContours, whose function declaration is as follows:


void drawContours(InputOutputArray image,
InputArrayOfArrays contours,
int contourIdx,
const Scalar& color,
int thickness = 1,
int lineType = 8,
InputArray hierarchy = noArray(),
 
int maxLevel = INT_MAX,
 
Point offset = Point())

Its parameters are explained as follows:

(1) image: Represents the input image matrix and draws the outline on it;
(2) contours: is the set of 1 series points obtained, representing multiple contours;
(3) contourIdx: it is an index, which represents the first contour in contours;
(4) color: The color to be filled. The monochrome can be set to Scalar(255), etc.
(5) thickness: The line thickness of Contour is drawn. If the parameter value is less than 0, it means that the area within the entire contour is filled;
(6) lineType: Connectivity of lines;
(7) hierarchy: Optional hierarchical information structure, which is the hierarchical information based on Contours obtained by findContours;
(8) maxLevel: The maximum level at which an outline is drawn. If level 0, draw a separate outline. If 1, draw the contour and the contour at the following level. If the value is 2, all the Outlines. If level 2, draw all class contours and all lower level 1 contours, and so on. If the value is negative, the function does not draw the sibling contour, but does so in ascending order until the child contour is abs(max_level)-1

(9) offset: Move the coordinates of each contour point according to the offset given. This parameter is used when the contour is extracted from some region of interest (ROI) and the ROI offset needs to be considered in the operation.

2. Demo code

Instance steps

Turn gray canny got a 2-value image findcontours looks for Outlines drawcontours contours

We wrote the demo code as follows:


#include<opencv2\opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
Mat src1, src2,gray_img, dst;
int value = 100;
int max_value = 255;
void demo(int, void*);
int main()
{
 // Found that outline --> cvtcolor-->canny get 2 Value image -->findcontours( Looking for contour )-->drawcontous()
 src1 = imread("C:\\Users\\ Ma Yingwei \\Desktop\\yuan1.jpg");
 //src2 = imread("C:\\Users\\ Ma Yingwei \\Desktop\\heibao1.png");
 if (src1.empty())
 {
 printf("cannot load!!\n");
 system("pause");
 return -1;
 }
 namedWindow("input", CV_WINDOW_AUTOSIZE);
 imshow("input",src1);
 namedWindow("output", CV_WINDOW_AUTOSIZE);
 cvtColor(src1,gray_img,CV_BGR2GRAY);
 createTrackbar("creattrackbar","output",&value,max_value,demo);
 demo(0, 0);
 waitKey(0);
 return 0;
}
void demo(int, void*)
{
 // Represent the image as src3 on 
 Mat src3 = Mat::zeros(src1.size(),CV_8UC3);
 vector<vector<Point>>contours;
 vector<Vec4i>hierarchy;
 Canny(gray_img,src2,value,value*2,3,false );
 findContours(src2,contours,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0));
 RNG rng(12345);
 for (size_t i = 0; i < contours.size(); i++)
 {
 Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
 drawContours(src3, contours, i,color,1,LINE_AA,hierarchy,0,Point(0,0));
 }
 imshow("output",src3);
}

Related articles: