There are many times when we need to get an outline of an object on the graph, OPENCV provides two functions findcontours () and drawcontours (), one is looking for the contour, one is the outline, the following describes the two functions: first, Findcontours ( )
void findcontours//extracts the contour for extracting the contour of the image
(
inputoutputarray image,//input image must be a 8-bit single channel image and should be converted to a two-
valued Outputarrayofarrays contours,//the detected contour, each profile is represented as a point vector
outputarray hierarchy,//Optional output vector containing the topology information of the image. The number of elements and the amount of contour detected are equal
int mode,//the outline type required and the desired return value way
int method,//Contour approximation method Point
offset = point ()
)
The cv_retr_external only detects the most outer contour, namely the C0. The first contour in Figure 2 points to the most external sequence, and there is no other connection.
Cv_retr_list detects all the outlines and saves them to the table (list), which is depicted in Figure 2, and the 9 profiles found are connected by H_prev and H_next. There is no vertical connection, no use of V_prev and V_next.
Cv_retr_comp detects all the contours and organizes them into two-tier structures, the first layer is the outer contour boundary, and the second is the boundary of the hole. From Figure 2 You can see the boundaries of the 5 outlines, where 3 contain holes. The outermost boundary C0 has two holes, and all the holes between the C0 are connected by H_prev and h_next pointers between each other.
The cv_retr_tree detects all the contours and re-establish the reticular contour structure. In Figure 2, the root node is the outermost boundary c0,c0 a hole h00, connected to another hole h01 in the same layer. Similarly, each hole has child nodes (relative to c000 and c010), and these child nodes and parent nodes are connected vertically. This step continues to the contour of the image's inner layer, which becomes the leaf node.
Note that method is the approximation of the contour
Cv_chain_code with freeman chain code output Contour, other methods output polygon (vertex sequence).
Cv_chain_approx_none converts all points in the chain code encoding to dots.
Cv_chain_approx_simple compression level, vertical or oblique section, save only the last point.
Cv_chain_approx_tc89_l1,cv_chain_qpprox_tc89_kcos uses one of the Teh-chin chain approximation algorithms.
Cv_link_runs is completely different from the above algorithm, connecting all the horizontal contours.
Second, drawcontours ()
void drawcontours//draws an outline that is used to draw the found outline of the image
(
Inputoutputarray image,//the image to draw the contour
inputarrayofarrays contours,/ /All input outlines, each profile is saved as a point vector
int contouridx,//Specifies the number to draw the outline, and if it is a negative, draw all the outlines
const scalar& color,//The color used to draw the outline
int thickness = 1,//the thickness of the line that draws the contour, if it is a negative number, the contour is filled with
int linetype = 8,/The connectivity of the line that draws the contour
inputarray hierarchy = Noarray () ,//about the optional parameters of the hierarchy, only the part of the outline will be used to draw the
int maxlevel = int_max,//The highest level of the drawing contour, this parameter is only valid when the hierarchy is valid
//maxlevel= 0, draw all the contours that belong to the same level as the input contour, i.e. the input contour and its adjacent contour
//maxlevel=1, and draw all the contours of the same level as the input contour with its child nodes.
//maxlevel=2, draws all the contours of the same level as the input profile with its child nodes and child nodes of the
child node Point offset = point ()
)
III. Implementation of the procedure
#include <opencv2/opencv.hpp> #include <iostream> using namespace std;
using namespace CV;
#define WINDOWN_1 "original" #define WINDOWN_2 "Canny map" #define WINDOWN_3 "effect map" Mat srcimage, Grayimage, Out_canny;
int min_thresh = 50;
int Max_thresh = 250;
Vector<vector<point>> g_vcontours;
Vector<vec4i> G_vhierarchy;
RNG g_rng (1234);
void find_draw_contours (int, void*);
int main () {srcimage = Imread ("d://vvoo//bmw_1.jpg");
Namedwindow (windown_1,1);
Imshow (windown_1, srcimage);
Cvtcolor (Srcimage, Grayimage, Color_bgr2gray);
Blur (Grayimage, Grayimage, Size (3, 3));
Createtrackbar ("CANNY value:", Windown_1, &min_thresh, Max_thresh, find_draw_contours);
Find_draw_contours (0, 0);
Waitkey (0);
return 0;
} void find_draw_contours (int, void*) {Canny (Grayimage, Out_canny, Min_thresh, Max_thresh *2, 3);
Imshow (windown_2, Out_canny);
Findcontours (Out_canny, G_vcontours, G_vhierarchy, Retr_tree, Chain_approx_simple, point (0, 0)); Mat Drawing = Mat::zeros (out_cAnny.size (), CV_8UC3); for (int i= 0;i <g_vcontours.size (); i++) {Scalar color = Scalar (g_rng.uniform (0, 255), G_rng.uniform (0, 255), g_rng
. uniform (0, 255));
Drawcontours (Drawing, g_vcontours, I, color, 2, 8, G_vhierarchy, 0, point ());
} imshow (Windown_3, Drawing); }
Results:
third, the actual application
Extract to the contour, in fact, we are more concerned about if these contours into the available features, that is, the outline of the description problem, there are many ways to choose, such as vectorization for polygons, rectangles, ellipses and so on. Some of these functions are provided in the OPENCV.
The contour is represented as a rectangle
Rect r = Boundingrect (Mat (contours[0));
Rectangle (result, R, Scalar (255), 2);
The contour is expressed as a round
float radius;
POINT2F Center;
Minenclosingcircle (Mat (contours[1]), center, RADIUS);
Circle (result, point (center), static_cast<int> (RADIUS), Scalar (255), 2);
The contour is expressed as a polygon
vector<point> Poly;
APPROXPOLYDP (Mat (contours[2]), Poly, 5, true);
Vector<point>::const_iterator ITP = Poly.begin ();
while (ITP!= (Poly.end ()-1))
{line
(result, *ITP, * (ITP + 1), Scalar (255), 2);
++ITP;
}
Line (result, *ITP, * (Poly.begin ()), Scalar (255), 2);
The contour is expressed as a convex polygon
vector<point> hull;
Convexhull (Mat (contours[3]), Hull);
Vector<point>::const_iterator ith = Hull.begin ();
while (Ith!= (Hull.end ()-1))
{line
(result, *ith, * (ith + 1), Scalar (255), 2);
++ith;
}
Line (result, *ith, * (Hull.begin ()), Scalar (255), 2);
In the program we draw rectangles, circles, polygons and polygons in turn. The final effect is as follows:
#include <opencv2\opencv.hpp> #include <iostream> using namespace CV;
using namespace Std;
#define WINDOW_1 "original" #define Window_2 "effect Chart" int min_area = 13;
int max_area = 100;
Vector<vector<point>> g_vcontours;
Vector<vec4i> G_vhierarchy;
RNG g_rng (12345);
Mat Srcimage,grayimage,b_grayimage,binaryimage;
Mat foreground, D_foreground, C_foreground;
void On_threshchange (int, void*);
int main () {Srcimage=imread ("d://vvoo//soldier.jpg", 1);
Cvtcolor (Srcimage, Grayimage, Color_bgr2gray);
Blur (Grayimage, B_grayimage, Size (3, 3));
Threshold (B_grayimage, binaryimage, 255, cv_thresh_binary);
Mat element_1 = getstructuringelement (Morph_rect, Size (3,3));
Mat element_2 = getstructuringelement (Morph_rect, Size (5,5));
Erode (binaryimage, foreground, element_1);
Dilate (foreground, d_foreground, element_2);
Namedwindow (Window_1, window_autosize); /*imshow (Window_1, srcimage); * Createtrackbar ("area value:", Window_1, &min_area, Max_area, On_threshchange);
On_threshchange (0, 0);
/* Imshow ("binary", binaryimage);
Imshow ("Morphological processing foreground", d_foreground); * */*imshow ("Canny", c_foreground); * * Waitkey (0);
return 0;
} void On_threshchange (int, void*) {Canny (D_foreground, C_foreground, 100, 200,3);
Findcontours (C_foreground, G_vcontours, G_vhierarchy, Cv_retr_external, Cv_chain_approx_none, point (0, 0));
Mat drawing = Mat::zeros (Srcimage.size (), CV_8UC3); for (int i = 0; i< g_vcontours.size (); i++) {drawcontours (drawing, G_vcontours, I, Scalar (255,255,255), 3, G_VH
Ierarchy, 0, point ()); Double area = Contourarea (Mat (g_vcontours[i));//Calculate Contour Area if (Area>min_area && area < MB) {Scalar col or = Scalar (g_rng.uniform (0, 255), G_rng.uniform (0, 255), G_rng.uniform (0, 255))//any value Rect Rect = Boundingrect (Mat (g_v
Contours[i]);//compute the outermost rectangular boundary of the point set rectangle (drawing, Rect,color, 2);
Rectangle (srcimage, rect,/*scalar (0,0,255) */color, 2);
Rectangle (c_foreground, rect, color, 2); }} imshow (Window_1, Srcimage);
Imshow (Window_2, drawing);
Imshow ("Canny", C_foreground); }
Do not understand where wrong, why the original srcimage on the original picture of the rectangle is basically not with the sliding button and change it. Solving.
Logically, the three-picture rectangular frame should be the same, but the last one is not the same as the first two, why.
v. reference materials
1.http://mobile.51cto.com/aengine-435442.htm
2.http://blog.csdn.net/qq_20823641/article/details/52143637