轮廓检测
轮廓检测也是图像处理中经常用到的。OpenCV-Python接口中使用cv2.findContours()函数来查找检测物体的轮廓。

实现
使用方式如下:

import cv2  
 
img = cv2.imread("./test.jpg")  #读取原始图片,彩色三通道图片
 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    #将图片转化成灰度图,灰度图是单通道的,单通道的像素值是原始img三通道的像素值的均值,所有像素的值取值范围是0~255
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)  #二值化灰度图图片,以127为门槛值,所有大于127像素值的像素取值255,所有小于127像素值的取值为0
 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)  #轮廓搜索,找到
cv2.drawContours(img,contours,-1,(0,0,255),3)  #绘制轮廓
 
cv2.imshow("img", img)  
cv2.waitKey(0)  
  

需要注意的是cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图,参见4、5两行。第六行是检测轮廓,第七行是绘制轮廓。

参数
第一个参数是寻找轮廓的图像;
第二个参数表示提取轮廓后,输出轮廓信息的组织形式,有四种(本文介绍的都是新的cv2接口):
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个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法

返回值

contour返回值
cv2.findContours()函数首先返回一个tuple,tuple中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。这个概念非常重要。在下面drawContours中会看见。通过

print (type(contours))
print (type(contours[0]))
print (len(contours))

以上的返回值是:

<class 'tuple'>    #表示tuple类型
<class 'numpy.ndarray'>  #表示numpy矩阵
2      #表示接口返回了2个轮廓,一个是矩形轮廓,一个是五角星轮廓

而countours[0]和countours[1]则分别存放的是像素点的坐标值 len(countours[0]),为4,表示有四个点坐标。
打印countours[0]

print(contours[0])

打印结果

[[[507 149]]
 [[507 380]]
 [[748 380]]
 [[748 149]]]

输出两个轮廓中存储的点的个数,可以看到,第一个轮廓中只有4个元素,**为何只用4个点表示轮廓呢?**这是因为我们采用了参数CHAIN_APPROX_SIMPLE,轮廓中压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标比如一个“正立”的矩形,只需4个顶点就能描述轮廓了。

hierarchy返回值
未完待续

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐