opencv basics 52-image contour learning 05-convex hull acquisition-cv2.convexHull()

Approximating polygons is a high approximation of contours, but sometimes, we wish to simplify it using the convex hull of a polygon.
A convex hull is similar to an approximating polygon, except that it is the outermost "convex" polygon of an object. A convex hull refers to a polygon that completely contains the original contour and is only composed of points on the contour. Every part of the convex hull is convex, that is, the straight line connecting any two points in the convex hull is inside the convex hull. In a convex hull, the interior angle of any three consecutive points is less than 180°.

For example, in Figure 12-25, the outermost polygon is the convex hull of the manipulator, and the part between the edge of the manipulator and the convex hull is called a convex defect (Convexity Defect), which can be used to deal with gesture recognition and other issues .

insert image description here

get convex hull

OpenCV provides 函数 cv2.convexHull()a convex hull for obtaining contours. The syntax of this function is:

hull = cv2.convexHull( points[, clockwise[, returnPoints]] )

The return value hull in the formula is the corner point of the convex hull.
The parameters in the formula are as follows:

  • points: outline.
  • clockwise: Boolean value. When the value is True, the corners of the convex hull will be arranged in a clockwise direction; when the value is False, the corners of the convex hull will be arranged in a counterclockwise direction.
  • returnPoints: Boolean value. The default value is True, the function returns the x/y axis coordinates of the corners of the convex hull; when it is False, the function returns the indices of the corners of the convex hull in the contour.

Example: observe the use of the parameter returnPoints in the function cv2.convexHull()

code show as below:

import cv2
o = cv2.imread('contours.bmp')
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
hull = cv2.convexHull(contours[0]) # 返回坐标值
print("returnPoints 为默认值 True 时返回值 hull 的值:\n",hull)
hull2 = cv2.convexHull(contours[0], returnPoints=False) # 返回索引值
print("returnPoints 为 False 时返回值 hull 的值:\n",hull2)

operation result:

returnPoints 为默认值 True 时返回值 hull 的值:
 [[[195 270]]

 [[195 383]]

 [[ 79 383]]

 [[ 79 270]]]
returnPoints 为 False 时返回值 hull 的值:
 [[3]
 [2]
 [1]
 [0]]

As can be seen from the program running results, the optional parameter returnPoints of the function cv2.convexHull():

  • When the default value is True, the function returns the x/y axis coordinates of the corner points of the convex hull. In this example, the coordinate values ​​of 4 contours are returned.
  • When False, the function returns the indices of the corner points of the convex hull in the contour, in this case 4 index values ​​of the contour are returned.

Example 2: Use the function cv2.convexHull() to obtain the convex hull of a contour.

code show as below:

import cv2
# --------------读取并绘制原始图像------------------
o = cv2.imread('hand.bmp')
cv2.imshow("original",o)
# --------------提取轮廓------------------
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
# --------------寻找凸包,得到凸包的角点------------------
hull = cv2.convexHull(contours[0])
# --------------绘制凸包------------------
cv2.polylines(o, [hull], True, (0, 255, 0), 2)
# --------------显示凸包------------------
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

insert image description here

convex defect

The part between the convex hull and the contour is called a convex defect. cv2.convexityDefects()Get convex defects using function in OpenCV . Its syntax format is as follows:

convexityDefects = cv2.convexityDefects( contour, convexhull )

The return value convexityDefects in the formula is the set of convex defect points. It is an array, and each row contains the values ​​[start point, end point, point on the contour furthest from the convex hull, approximate distance from the furthest point to the convex hull].

需要注意的是,返回结果中[起点,终点,轮廓上距离凸包最远的点, the approximate distance from the furthest point to the convex hull] The first three values ​​are the indexes of the contour points, so you need to find them in the contour points.
The parameters in the formula are as follows:

  • contour is the contour.
  • convexhull is the convex hull.

It should be noted that when calculating convex defects with cv2.convexityDefects(), the convex hull should be used as a parameter. When looking for the convex hull, the value of the parameter returnPoints of the function cv2.convexHull() used must be False.
In order to allow everyone to observe the convex defect point set more intuitively, we try to display the convex defect point set in a picture. The implementation method is to connect the starting point and the ending point with a line, and draw a circle at the farthest point. Below we use an example to demonstrate the above operation.

Example 2: Calculate convex defects using the function cv2.convexityDefects().

code show as below:

import cv2
#----------------原图--------------------------
img = cv2.imread('hand.bmp')
cv2.imshow('original',img)
#----------------构造轮廓--------------------------
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255,0)
contours, hierarchy = cv2.findContours(binary,
 cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
#----------------凸包--------------------------
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
print("defects=\n",defects)
#----------------构造凸缺陷--------------------------
for i in range(defects.shape[0]):
 s,e,f,d = defects[i,0]
 start = tuple(cnt[s][0])
 end = tuple(cnt[e][0])
 far = tuple(cnt[f][0])
 cv2.line(img,start,end,[0,0,255],2)
 cv2.circle(img,far,5,[255,0,0],-1)
#----------------显示结果,释放图像--------------------------
cv2.imshow('result',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

operation result:

defects=
 [[[    0   102    51 21878]]

 [[  103   184   150 13876]]

 [[  185   233   220  4168]]

 [[  233   238   235   256]]

 [[  238   240   239   247]]

 [[  240   294   255  2715]]

 [[  294   302   295   281]]

 [[  302   304   303   217]]

 [[  305   311   306   114]]

 [[  311   385   342 13666]]

 [[  385   389   386   395]]

 [[  389   489   435 20327]]]

insert image description here

Determine if the contour is convex

In OpenCV, the function cv2.isContourConvex() can be used to determine whether the contour is convex, and its syntax format is:

retval = cv2.isContourConvex( contour )

In the formula:

  • The return value retval is a Boolean value. When True, the contour is convex; otherwise, it is not.
  • The parameter contour is the contour to be judged.

Example: Use the function cv2.isContourConvex() to determine whether the contour is convex.

code show as below:

import cv2
o = cv2.imread('hand.bmp')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,
 cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
#--------------凸包----------------------
image1=o.copy()
hull = cv2.convexHull(contours[0])
cv2.polylines(image1, [hull], True, (0, 255, 0), 2)
print("使用函数 cv2.convexHull()构造的多边形是否是凸形的:",
cv2.isContourConvex(hull))
cv2.imshow("result1",image1)
#------------逼近多边形--------------------
image2=o.copy()
epsilon = 0.01*cv2.arcLength(contours[0],True)
approx = cv2.approxPolyDP(contours[0],epsilon,True)
image2=cv2.drawContours(image2,[approx],0,(0,0,255),2)
print("使用函数 cv2.approxPolyDP()构造的多边形是否是凸形的:",
 cv2.isContourConvex(approx))
cv2.imshow("result2",image2)
#------------释放窗口--------------------
cv2.waitKey()
cv2.destroyAllWindows()

operation result:

使用函数 cv2.convexHull()构造的多边形是否是凸形的: True
使用函数 cv2.approxPolyDP()构造的多边形是否是凸形的: False

insert image description here

From the above running results, it can be seen that:

  • After using the function cv2.contourContourConvex() to construct a convex hull, use the function cv2.isContourContourConvex() to judge the drawn convex hull. The return value is True, indicating that the contour is convex.
  • After using the function cv2.approxPolyDP() to construct the approximate polygon, use the function cv2.isContourConvex() to judge the drawn approximate polygon, and the return value is False, indicating that the contour (polygon) is not convex.

The original picture of the experiment:

insert image description here

Guess you like

Origin blog.csdn.net/hai411741962/article/details/132192433