OpenCV The outline of
1.1 What is the outline
It can be thought of as a simple continuous point （ Connected to the border ） Connected curves , Having the same color or grayscale . Contour is very useful in shape analysis and object detection and recognition .
- For accuracy , To use binary images . It needs to be thresholded or Canny boundary detection .
- The function to find the contour modifies the original image . If you want to continue using the original image later , The original image should be stored in other variables .
- stay OpenCV in , Looking for contours is like a super white object on a black background . You should remember , The object you're looking for should be white and the background should be black .
How to find the contour in a binary image .
function cv2.findContours() There are three parameters , The first is the input image , The second is the contour retrieval mode , The third is contour approximation . There are three return values , The first is the image , The second is the outline , The third is （ Contoured ） Chromatography structure . outline （ Second return value ） It's a Python list , It stores all the contours in this image . Every contour is a Numpy Array , Include object boundary points （x,y） Coordinates of .
1.2 How to draw the outline
function cv2.drawContours() Can be used to draw outlines . It can draw any shape according to the boundary points you provide . Its first parameter is the original image , The second parameter is the contour , One python list , The third parameter is the index of the contour （ It's very useful in drawing independent outlines , When set to -1 All contours are drawn ）. The next parameters are the color and thickness of the contour .
Draw all the outlines on one image ：
import numpy as np import cv2 img = cv2.imread('1024.jpg') imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imgray,127,255,0) image ,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) # Drawing individual outlines , Like the fourth outline #imag = cv2.drawContour(img,contours,-1,(0,255,0),3) # But most of the time , The following method is more useful imag = cv2.drawContours(img,contours,3,(0,255,0),3) while(1): cv2.imshow('img',img) cv2.imshow('imgray',imgray) cv2.imshow('image',image) cv2.imshow('imag',imag) if cv2.waitKey(1) == ord('q'): break cv2.destroyAllWindows()
1.3 The approximate method of contour
As mentioned earlier, a contour is a boundary of a shape with the same gray value , It will store all the （x,y） coordinate . Actually, we don't need all the dots , When you need a straight line , You can find two endpoints .cv2.CHAIN_APPROX_SIMPLE Can achieve . It removes redundant points from the contour , Compress the contour , So as to save memory expenses .
Let's use the matrix to demonstrate , Draw a blue circle on each coordinate in the outline list . The first display uses cv2.CHAIN_APPROX_NONE The effect of , altogether 734 A little bit , The second graph is using cv2.CHAIN_APPROX_SIMPLE Result , Only 4 A little bit .
2. Contour feature
The moment of the image can help us calculate the centroid of the image , Area etc. .
function cv2.moments() The calculated moment is returned as a dictionary .
import numpy as np import cv2 img = cv2.imread('1024.jpg',0) ret,thresh = cv2.threshold(img,127,255,0) image,contours,hierarchy=cv2.findContours(thresh,1,2) cnt=contours M=cv2.moments(cnt) print(M)
According to the values of these moments , We can calculate the center of gravity of the object ：
2.2 Contour area
You can use functions cv2.contourArea() To calculate the , You can also use moments （0 moment ）,M['m00'].
2.3 Contour circumference
Also known as arc length . You can use functions cv2.arcLength() To calculate the . The second parameter of this function can be used to specify that the shape of the object is closed （True）, It's still open （ A curve ）.
perimeter = cv2.arcLength(cnt,True)
2.4 The outline is approximate
The contour shape is approximated to another contour shape composed of fewer points , The number of points in the new contour is determined by the accuracy we set , The use of Douglas-Peucker Algorithm , You can do it yourself Google.
Suppose we're looking for a rectangle in an image , But for various reasons in the image, we can't get a perfect rectangle , It is a “ Bad shape ”, Now you can use this function to approximate the shape , The second parameter is epsilon, It is the maximum distance from the original contour to the approximate contour , It's an accuracy parameter .
epsilon=0.1*cv2.arcLength(cnt,True) approx = cv2.approxPolyDP(cnt,epsilon,True)
2.5 convex hull
The convex hull is similar to the contour , But it's different , Although in some cases they give the same result . function cv2.convexHull() It can be used to detect whether a curve has convex defects , And it can correct the defects . Generally speaking , Convex curves are always convex , At least it's flat . If there's a dent, it's called a convex defect . For example, the hand in the picture below , The red curve shows the convex hull of the hand , Convex defects are marked with double arrows .
hull = cv2.convexHull(points,hull,clockwise,returnPoints)
- points The profile we're going to pass in
- hull Output , Usually you don't need
- clockwise Direction signs , If set to True, The output convex hull is clockwise , Otherwise it's counter clockwise .
- returnPoints The default value is True. It will return the coordinates of the points on the convex hull , If set to False, The point on the contour corresponding to the convex hull point is returned .
To get the convex hull of the above figure , You can use the following command ：
But if you want to get convex defects , Need to put returnPoints Set to False. Take the upper rectangle as an example , First of all, we find his outline from cnt. Now the returnPoints Set to True Find convex hull , What you get is the four corners of the rectangle . hold returnPoints Set to False, What you get is the index of the contour points .
2.6 Convexity detection
function cv2.isContourConvex() You can detect whether a curve is convex or not . It can only return True perhaps False.
2.7 Border rectangle
Straight border rectangle , A straight rectangle , No rotation . It doesn't take into account whether the object is rotating . So the area of the bounding rectangle is not the smallest . You can use functions cv2.boundingRect() Find out
#（x,y） Is the coordinates of the upper left corner of the rectangle ,（w,h） It's the width and height of the rectangle x,y,w,h=cv2.boundingRect(cnt) img=cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
Rotating border rectangle , This bounding rectangle is the smallest in area , Because it takes into account the rotation of the object . Use functions cv2.minAreaRect(). Back to a Box2D structure , It contains the coordinates of the top corner of the rectangle （x,y） The width and height of the rectangle （w,h） And the angle of rotation . But to draw this rectangle, you need rectangular 4 Corner points , You can do this through a function cv2.boxPoints() get .
The green one is a straight rectangle , Red is the rotating rectangle .
2.8 The smallest circumscribed circle
function cv2.minEnclosingCircle() It can help us find the circumcircle of an object . It's the smallest of all circles that can contain objects .
(x,y),radius = cv2.minEnclosingCircle(cnt) center = (int(x),int(y)) radius = int(radius) img = cv2.circle(img,center,radius,(0,255,0),2)
2.9 Ellipse fitting
Using functions cv2.ellipse(), The return value is actually the inscribed circle of the rotated bounding rectangle .
ellipse = cv2.fitEllipse(cnt) img = cv2.ellipse(img,ellipse,(0,255,0),2)
2.10 Straight line fitting
A line can be fitted from a set of points , Similarly, we can fit a straight line for the white points in the image .
rows,cols = img.shape[:2] [vx,vy,x,y]=cv2.fitLine(cnt,cv2.DIST_L2,0,0.01,0.01) lefty=int((x*vy/vx)+y) righty=int(((cols-x)*vy/vx)+y) img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)