轮廓检测cv2.findContours()
轮廓检测
轮廓检测也是图像处理中经常用到的。OpenCV-Python接口中使用cv2.findContours()函数来查找检测物体的轮廓。
实现
使用方式如下:
01 02 03 04 05 06 07 08 | import cv2 img = cv2.imread( "./test.jpg" ) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray, 127 , 255 ,cv2.THRESH_BINARY) 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两行。第六行是检测轮廓,第七行是绘制轮廓。
结果
原图如下:
检测结果如下:
注意,findcontours函数会“原地”修改输入的图像。这一点可通过下面的语句验证:
01 02 03 | cv2.imshow( "binary" , binary) contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cv2.imshow( "binary2" , binary) |
执行这些语句后会发现原图被修改了。
cv2.findContours()函数
函数的原型为
01 | cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]]) |
opencv2返回两个值:contours:hierarchy。注:opencv3会返回三个值,分别是img, countours, hierarchy
参数
第一个参数是寻找轮廓的图像
第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口)
01 02 03 04 | cv2.RETR_EXTERNAL #表示只检测外轮廓 cv2.RETR_LIST #检测的轮廓不建立等级关系 cv2.RETR_CCOMP #建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。 cv2.RETR_TREE #建立一个等级树结构的轮廓。 |
第三个参数method为轮廓的近似办法
01 02 03 | 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 近似算法 |
返回值
cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。
contour返回值
cv2.findContours()函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。这个概念非常重要。在下面drawContours中会看见。通过
01 02 03 | print ( type (contours)) print ( type (contours[ 0 ])) print ( len (contours)) |
可以验证上述信息。会看到本例中有两条轮廓,一个是五角星的,一个是矩形的。每个轮廓是一个ndarray,每个ndarray是轮廓上的点的集合。
由于我们知道返回的轮廓有两个,因此可通过
01 | cv2.drawContours(img,contours, 0 ,( 0 , 0 , 255 ), 3 ) |
和
01 | cv2.drawContours(img,contours, 1 ,( 0 , 255 , 0 ), 3 ) |
分别绘制两个轮廓,关于该参数可参见下面一节的内容。同时通过
01 02 | print ( len (contours[ 0 ])) print ( len (contours[ 1 ])) |
输出两个轮廓中存储的点的个数,可以看到,第一个轮廓中只有4个元素,这是因为轮廓中并不是存储轮廓上所有的点,而是只存储可以用直线描述轮廓的点的个数,比如一个“正立”的矩形,只需4个顶点就能描述轮廓了。
hierarchy返回值
此外,该函数还可返回一个可选的hiararchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。
通过
01 02 03 04 | print ( type (hierarchy)) print (hierarchy.ndim) print (hierarchy[ 0 ].ndim) print (hierarchy.shape) |
可以看出,hierarchy本身包含两个ndarray,每个ndarray对应一个轮廓,每个轮廓有四个属性。
轮廓的绘制
OpenCV中通过cv2.drawContours在图像上绘制轮廓。
cv2.drawContours()函数
01 | cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]]) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!