1. Contour extraction
Use threshold segmentation or edge extraction to obtain binary images; objects need to be white and backgrounds must be black
import numpy as np
import cv2 as cv
im = cv.imread('test.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
im2, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
2. Display the outline
Show all contours: cv.drawContours(img, contours, -1, (0,255,0), 3)
Draw a separate 4th contour: cv.drawContours(img, contours, 3, (0,255,0), 3)
Useful practice: cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0,255,0), 3)
Contour approximation method
cv.CHAIN_APPROX_NONE: save all contour points
cv.CHAIN_APPROX_SIMPLE: save the start and end points of the line
3. Contour features
(1) Moment: find the center
import numpy as np
import cv2 as cv
img = cv.imread('star.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
M = cv.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
(2) Area: M['m00']
area = cv.contourArea(cnt)
The contour points are: A(1,1), B(1,2), C(2,2), D(2,1). First select the points A and B, and the cross product of the vectors OA and OB can be obtained Triangle OAB area (with direction), note: the vector cross product has a direction, and the modulus of the cross product is the area of the parallelogram. Then select two points B and C to calculate the area of OBC (with direction), the difference of the area of triangle OAB and OBC with direction is the area of triangle ABC.
(A,B):1*2-1*1=1
(B,C):1*2-2*2=-2
(C,D):2*1-2*2=-2
(D,A):2*1-1*1=1
S=(1-2-2+1)/2
(3) Contour perimeter
perimeter = cv.arcLength(cnt,True)
(4) Contour approximation
epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)
(5) Check convexity: if it is convex, return true, otherwise return false
k = cv.isContourConvex(cnt)
(6) Border rectangle
直线边框矩形:(x,y)是矩形的左上角点,(w,h)是举行的宽和高
x,y,w,h = cv.boundingRect(cnt)
cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
旋转矩形:
rect = cv.minAreaRect(cnt)
box = cv.boxPoints(rect) #( center (x,y), (width, height), angle of rotation )
box = np.int0(box)
cv.drawContours(img,[box],0,(0,0,255),2)
(7) Minimum circumscribed circle
(x,y),radius = cv.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cv.circle(img,center,radius,(0,255,0),2)
(8) Ellipse fitting
ellipse = cv.fitEllipse(cnt)
cv.ellipse(img,ellipse,(0,255,0),2)
(9) Straight line fitting
rows,cols = img.shape[:2]
[vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cv.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
3. Contour characteristics
(1) Aspect ratio
x,y,w,h = cv.boundingRect(cnt)
aspect_ratio = float(w)/h
(2) Elongation
area = cv.contourArea(cnt)
x,y,w,h = cv.boundingRect(cnt)
rect_area = w*h
extent = float(area)/rect_area
(3) Hardness
area = cv.contourArea(cnt)
hull = cv.convexHull(cnt)
hull_area = cv.contourArea(hull)
solidity = float(area)/hull_area
(4) Equivalent diameter
area = cv.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi)
(5) Direction
(x,y),(MA,ma),angle = cv.fitEllipse(cnt)
(6) Maximum value, minimum value and position
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(imgray,mask = mask)
(7) Average color and brightness
mean_val = cv.mean(im,mask = mask)
4, convex hull
(1) Convex defect
The convex hull is very similar to the polygon approximation, except that it is the outermost "convex" polygon of the object: the straight line connecting any two points in the set A is inside A, then the set A is called convex. As shown in the figure below, the red part is the convex hull of the palm, and the double arrow part represents Convexity Defects. Convexity defects are often used for gesture recognition, etc.:
# 1.先找到轮廓
img = cv2.imread('convex.jpg', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
image, contours, hierarchy = cv2.findContours(thresh, 3, 2)
cnt = contours[0]
# 2.寻找凸包,得到凸包的角点
hull = cv2.convexHull(cnt)
# 3.绘制凸包
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.polylines(image, [hull], True, (0, 255, 0), 2)
(2) Point to contour distance
The cv2.pointPolygonTest() function calculates the shortest distance from the point to the contour (that is, the vertical line), also known as the polygon test:
dist = cv2.pointPolygonTest(cnt, (100, 100), True) # -3.53
When parameter 3 is True, it indicates the calculated distance value: the value of the point outside the contour is negative, the value of the point on the contour is 0, and the value of the point inside the contour is positive; when the parameter 3 is False, only -1/0/1 is returned to indicate The position of the point relative to the contour, the distance is not calculated.