轮廓

  轮廓就是一群连续的点组成的曲线,用来进行形状分析、目标检测与识别。

  • 使用二值图像获取更好的精度,所以在应用轮廓检测之前进行阈值化处理或边缘检测;
  • 在Opencv中,轮廓检测是从黑色背景中检测白色物体。

查找轮廓

使用cv2.findcontours()查找轮廓

1
2
3
4
5
6
7
import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

cv2.findcontours()有三个参数:

  1. 第一个是输入图像,为经过阈值处理或边缘检测的二值图像。
  2. 第二个是轮廓查找方式,有四种:(RetrievalModesand轮廓层级)
    • cv2.RETR_EXTERNAL 表示只检测外轮廓
    • cv2.RETR_LIST 检测的轮廓不建立等级关系
    • cv2.RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
    • cv2.RETR_TREE 建立一个等级树结构的轮廓。
  3. 第三个是轮廓逼近方法,有四种:(ContourApproximationModes
    )
    • cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
    • cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    • cv.CHAIN_APPROX_TC89_L1 和 cv.CHAIN_APPROX_TC89_KCOS 应用Teh-Chin链逼近算法的一种风格。

有三个返回值:

  1. image是原来的二值化图片;
  2. contours是找到的轮廓,以数组的形式储存;
  3. hierarchy是轮廓间的层级关系

绘制轮廓

采用cv2.drawContours

1
img = cv2.drawContours(img, contours, -1, (0,255,0), 3)

一共有五个参数:

  1. img 即源图像,作图的画布
  2. contours 是储存轮廓的数组
  3. 轮廓的索引,-1表示绘制所有的轮廓,0表示第一个,以此类推
  4. BGR表示的颜色,轮廓的颜色
  5. 轮廓的像素值

更多情况下,先获取所需的轮廓,再进行绘制

1
2
cnt = contours[1]
img = cv2.drawContours(img, [cnt], 0, (0,255,0), 3)

轮廓特征

用于计算轮廓的特征,如面积、周长、最小外接矩形等。

面积

1
area = cv2.contourArea(cnt)

这是用几何方法计算轮廓的面积,有小数。如果统计二值图中像素点的个数,可以使用area = cv2.contourArea(cnt)

周长

1
perimeter = cv2.arcLength(cnt, True)

第二个参数表示轮廓是否闭合,闭合为True

图像矩

1
M = cv2.moments(cnt)

计算图像的各种几何特征,详细参考

计算质心

1
cx, cy = M['m10'] / M['m00'], M['m01'] / M['m00']

外接矩形

外接矩形有两种,如下图,绿色为不考虑旋转的外接矩形,蓝色是最小外接矩形。
No1

1
2
3
4
5
# 外接矩形
x, y, w, h = cv2.boundingRect(cnt)
# 最小外接矩形
rect = cv2.minAreaRect(cnt)
box = np.int0(cv2.boxPoints(rect)) # 矩形的四个角点取整

外接圆

1
2
3
4
# 最小外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)
(x, y, radius) = np.int0((x, y, radius)) # 圆心和半径取整
cv2.circle(img_color2, (x, y), radius, (0, 0, 255), 2)

拟合椭圆

1
2
ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(img_color2, ellipse, (255, 255, 0), 2)

形状匹配[2]

cv2.matchShapes()检测两个轮廓间的相似度,返回值越小,越相似

多边形逼近[2]

cv2.approxPolyDP()用于多边形逼近

1
approx = cv2.approxPolyDP(cnt, 3, True)

第二个参数是多边形轮廓接近实际轮廓的程度,值越小,越精确;第三个参数表示是否闭合

凸包[2]

cv2.convexHull()

点到轮廓的距离[2]

cv2.pointPolygonTest()计算点到轮廓的最短距离,也就是垂线。

reference

  1. OpenCV-Python Tutorials
  2. ex2tron/OpenCV-Python-Tutorial