CH09-图像轮廓

1. 什么是轮廓

轮廓是由一系列具有相同或类似的 BGR 值或灰度值的点构成的曲线;边缘是数字图像中亮度变化明显的点所构成的曲线.

边缘检测是检测图像的边缘,也就是图像差异比较大的地方;轮廓检测是提取出图像的轮廓,轮廓可能是边缘的一部分.

边缘检测一般会将图像中边界的像素点标记为 1, 其余部分标记为 0,只有两种取值;轮廓提取则是将整个轮廓上的所有像素点的数值保留下来,因此取值比较多样.

2. 轮廓的查找与绘制

2.1 轮廓查找

contours, hierarchy = cv2.findContours(image, mode, mechod)

参数 说明
image 原图像
mode 寻找轮廓的模式
method 找到轮廓后的保存方式
contours 找到的轮廓,为列表的形式,列表中是一个个小的列表,每个小列表代表一条轮廓线
hierarchy 轮廓之间的结构关系

寻找轮廓的模式(mode)一般有以下 4 种:

序号 模式参数 说明
1 cv2.RETR_EXTERNAL 只检测外轮廓
2 cv2.RETR_LIST 检测的轮廓不建立等级关系
3 cv2.RETR_CCOMP 建立两个等级的轮廓:最外层与内层
4 cv2.RETR_TREE 建立一个等级树结构的轮廓

找到轮廓后的保存方式(method):

序号 模式参数 说明
1 cv2.CHAIN_APPROX_NONE 保存找到的轮廓中的所有点
2 cv2.CHAIN_APPROX_SIMPLE 将找到的轮廓上额冗余点去掉,压缩轮廓,从而节省内存空间,节省内存主要是因为其会压缩垂直、水平、对角方向,只保留端点

2.2 轮廓绘制

dst = cv2.drawContours(image, contours, contoursIdx, color, thickness = None, lineType = None)

参数 说明
image 在哪张轮廓上绘制轮廓
contours 需要绘制的轮廓,必须以列表的形式传入,且列表内的元素也必须是列表
contoursIdx 轮廓的索引,当设置为-1 时,会绘制出所有传入的 contours
color 线条的颜色
thickness 线条的宽度
lineType 线条的类型
dst 绘制后输出的图像

2.3 轮廓的查找与绘制实例

# 读取图像
img = cv2.imread("./img/CH09-01.jpg")
x = img.shape[0]
y = img.shape[1]

# 转换为灰度值
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 高斯模糊
gauss = cv2.GaussianBlur(grey, (3, 3), 0)

# 边缘检测
edges = cv2.Canny(gauss, 50, 150)

# 去噪处理
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)

# 寻找边缘
contours, hierarchy = cv2.findContours(closed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 画出轮廓
out = cv2.drawContours(img, contours, -1, (0, 255, 0), 1)

# 图像显示
cv2.namedWindow('out', cv2.WINDOW_NORMAL)
cv2.resizeWindow('out', int(y/2), int(x/2))
cv2.imshow('out', img)
cv2.waitKey(0)
cv2.destroyAllWindows()