2. 函数实现
轮廓提取的原理:先通过阈值分割提取目标物体,再通过边缘检测提取目标物体轮廓。一个轮廓就是一系列的点(像素),这些点构成了一个有序的点集合。
使用 cv2.findContours [ˈkɑnˌtʊrz] 函数可以用来检测图像的边缘。
contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
image:输入图像(二值图,而非灰度图,注意)
mode:轮廓检索模式:
cv2.RETR_EXTERNAL:只检索最外面的轮廓;
cv2.RETR_LIST:检索所有的轮廓,并将其保存到一条链表中;
cv2.RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
cv2.RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;
method:轮廓逼近方法:
cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,相邻的两个点的像素位置差不超过 1,即 max(abs(x1-x2),abs(y2-y1))==1,一般不会用到;
cv2.CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需 4 个点来保存轮廓信息。
contours:返回的轮廓;
hierachy [ˈhī(ə)ˌrärkē]:每条轮廓对应的属性;
offset:每个轮廓点移动的可选偏移量。
返回结果是等高线和层次结构。
轮廓提取之后,还要通过 cv2.drawContours 函数绘制轮廓:
drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
image:输入图像;
contours:轮廓,在 Python 中是一个 list,就是 cv2.findContours 函数返回的点集,一个列表;
contourIdx:轮廓的索引,指定绘制轮廓 list 中的哪条轮廓,要绘制所有轮廓,传递-1;
color:颜色;
thickness [ˈθɪknəs] :厚度,如果是-1,表示填充;
lineType:线型;
hierarchy:层次结构的可选信息;
maxLevel:绘制轮廓的最大级别,0:仅绘制指定的轮廓,1:绘制轮廓和所有嵌套轮廓,2:绘制轮廓,所有嵌套轮廓,所有嵌套到嵌套的轮廓;
offset:轮廓偏移参数。
了解如上信息就可以有如下完整代码:
"""
Author: Will Wang
Email: WillWang1998@163.com
"""
import cv2
color_red = (0, 0, 255) # 画笔颜色(BGR)
img = cv2.imread('tyut_logo.png')
img = cv2.resize(img, (512, 512))
img_c = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 阈值二值化
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 寻找轮廓
cv2.drawContours(img, contours, -1, color_red, 2) # 绘制轮廓到img(注意原图会被改变)
cv2.imshow('origin', img_c) # 显示原图
cv2.imshow('findContours', img) # 显示绘制轮廓后的图像
cv2.waitKey(0)
cv2.destroyAllWindows()
你也可以对自己的图像进行测试。