# 4.2. 轮廓特征¶

## 4.2.1. 目标¶

• 找出轮廓的不同特征，如面积、周长、质心、包围盒等

• 您将看到许多与轮廓相关的功能。

## 4.2.2. 一。瞬间¶

>>> %matplotlib inline
>>> import matplotlib.pyplot as plt
>>>
>>> import cv2
>>> import numpy as np
>>>

>>> img = cv2.imread('/cvdata/star.png', 0)

>>> plt.imshow(img)

<matplotlib.image.AxesImage at 0x7f2aec184cc0>

>>> ret,thresh = cv2.threshold(img,127,255,0)

>>> ret

127.0

>>> plt.imshow(thresh)

<matplotlib.image.AxesImage at 0x7f2aec0e7780>

>>> contours,hierarchy,aa = cv2.findContours(thresh, 1, 2)

>>> contours.shape

(400, 640)

>>> aa.shape

(1, 22, 4)

>>> cnt = contours[0]
>>> M = cv2.moments(cnt)
>>> print (M)

{'m00': 0.0, 'm10': 0.0, 'm01': 0.0, 'm20': 0.0, 'm11': 0.0, 'm02': 0.0, 'm30': 0.0, 'm21': 0.0, 'm12': 0.0, 'm03': 0.0, 'mu20': 0.0, 'mu11': 0.0, 'mu02': 0.0, 'mu30': 0.0, 'mu21': 0.0, 'mu12': 0.0, 'mu03': 0.0, 'nu20': 0.0, 'nu11': 0.0, 'nu02': 0.0, 'nu30': 0.0, 'nu21': 0.0, 'nu12': 0.0, 'nu03': 0.0}


>>> cx = int(M['m10']/M['m00'])
>>> cy = int(M['m01']/M['m00'])

---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

<ipython-input-78-6f707285d91a> in <module>()
----> 1 cx = int(M['m10']/M['m00'])
2 cy = int(M['m01']/M['m00'])

ZeroDivisionError: float division by zero


## 4.2.3. 2。等高线面积¶

>>> for x in hierarchy:
>>>     area = cv2.contourArea(x)
>>>     print(area)

4.0
4.0
2.0
2.0
8.5
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
2.0
76185.5


## 4.2.4. 三。等高线周长¶

>>> for cnt in hierarchy:
>>>     perimeter = cv2.arcLength(cnt,True)
>>>     print(perimeter)

7.656854152679443
7.656854152679443
5.656854152679443
5.656854152679443
11.071067690849304
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
5.656854152679443
1680.687520623207


## 4.2.5. 四。轮廓近似¶

>>> for cnt in hierarchy:
>>>     epsilon = 0.1*cv2.arcLength(cnt,True)
>>>     approx = cv2.approxPolyDP(cnt,epsilon,True)
>>>     print(epsilon, approx)

0.7656854152679444 [[[175 338]]

[[176 337]]

[[178 338]]

[[177 339]]]
0.7656854152679444 [[[102 338]]

[[103 337]]

[[105 338]]

[[104 339]]]
0.5656854152679444 [[[174 337]]

[[175 336]]

[[176 337]]

[[175 338]]]
0.5656854152679444 [[[173 336]]

[[174 335]]

[[175 336]]

[[174 337]]]
1.1071067690849306 [[[413 286]]

[[416 285]]

[[417 287]]

[[415 288]]]
0.5656854152679444 [[[416 285]]

[[417 284]]

[[418 285]]

[[417 286]]]
0.5656854152679444 [[[412 285]]

[[413 284]]

[[414 285]]

[[413 286]]]
0.5656854152679444 [[[417 284]]

[[418 283]]

[[419 284]]

[[418 285]]]
0.5656854152679444 [[[411 284]]

[[412 283]]

[[413 284]]

[[412 285]]]
0.5656854152679444 [[[421 281]]

[[422 280]]

[[423 281]]

[[422 282]]]
0.5656854152679444 [[[422 280]]

[[423 279]]

[[424 280]]

[[423 281]]]
0.5656854152679444 [[[423 279]]

[[424 278]]

[[425 279]]

[[424 280]]]
0.5656854152679444 [[[424 278]]

[[425 277]]

[[426 278]]

[[425 279]]]
0.5656854152679444 [[[425 277]]

[[426 276]]

[[427 277]]

[[426 278]]]
0.5656854152679444 [[[426 276]]

[[427 275]]

[[428 276]]

[[427 277]]]
0.5656854152679444 [[[431 272]]

[[432 271]]

[[433 272]]

[[432 273]]]
0.5656854152679444 [[[432 271]]

[[433 270]]

[[434 271]]

[[433 272]]]
0.5656854152679444 [[[433 270]]

[[434 269]]

[[435 270]]

[[434 271]]]
0.5656854152679444 [[[434 269]]

[[435 268]]

[[436 269]]

[[435 270]]]
0.5656854152679444 [[[435 268]]

[[436 267]]

[[437 268]]

[[436 269]]]
0.5656854152679444 [[[436 267]]

[[437 266]]

[[438 267]]

[[437 268]]]
168.06875206232073 [[[639 316]]

[[  0 399]]]


## 4.2.6. 5个。凸壳¶

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


• 是我们穿过的轮廓。

• hull 是输出，通常我们会避免它。

• 顺时针方向的 ：方向标志。如果是的话 True ，输出凸包为顺时针方向。否则，它是逆时针方向的。

• 返回点 ：默认情况下， True . 然后返回外壳点的坐标。如果 False ，它返回与外壳点相对应的轮廓点的索引。

>>> hull = cv2.convexHull(cnt)


## 4.2.7. 6。检查凸性¶

>>> k = cv2.isContourConvex(cnt)


## 4.2.8. 7号。边界矩形¶

### 7.a.直边矩形¶

>>> x,y,w,h = cv2.boundingRect(cnt)
>>> img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)


### 7.b.旋转矩形¶

>>> rect = cv2.minAreaRect(cnt)
>>> box = cv2.boxPoints(rect)
>>> box = np.int0(box)
>>> im = cv2.drawContours(img,[box],0,(0,0,255),2)

>>> plt.imshow(im)

<matplotlib.image.AxesImage at 0x7f2aec05f2b0>


## 4.2.9. 8个。最小包围圈¶

>>> (x,y),radius = cv2.minEnclosingCircle(cnt)
>>> center = (int(x),int(y))

>>> plt.imshow(img)

<matplotlib.image.AxesImage at 0x7f2aec032f98>


## 4.2.10. 9号。拟合椭圆¶

>>> ellipse = cv2.fitEllipse(cnt)
>>> im = cv2.ellipse(im,ellipse,(0,255,0),2)

>>> plt.imshow(im)

<matplotlib.image.AxesImage at 0x7f2ae677dc50>


## 4.2.11. 10个。装线¶

>>> 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)

>>> plt.imshow(img)

<matplotlib.image.AxesImage at 0x7f2ae67648d0>