赞
踩
目录
轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。
谈起轮廓不免想到边缘,它们确实很像。简单的说,轮廓是连续的,边缘并不全都连续(下图)。其实边缘主要是作为图像的特征使用,比如可以用边缘特征可以区分脸和手,而轮廓主要用来分析物体的形态,比如物体的周长和面积等,可以说边缘包括轮廓。
寻找轮廓的操作一般基于二值化图,所以通常会使用阈值分割或Canny边缘检测先得到二值图。
经验之谈:寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在
寻找轮廓时会找到图片最外面的一个框。
代码:
- import cv2
-
- img = cv2.imread('handwriting.jpg')
- img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- # 使用Otsu自动阈值,注意用的是cv2.THRESH_BINARY_INV
- ret, thresh = cv2.threshold(
- img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
- # cv2.imshow("thresh", thresh)
- """
- 寻找轮廓方法三个参数:输入图像,轮廓检索模式,轮廓近似方法
- 返回值contours是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy,下边详解
- """
- contours, hierarchy = cv2.findContours(
- thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
- print(len(contours)) # 结果应该为2,两个轮廓
- cnt = contours[1]
- """
- 绘制轮廓:
- 第一个参数是一张图片,可以是原图或者其他。
- 第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。
- 第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。
- 接下来的参数是轮廓的颜色和厚度。
- """
- cv2.drawContours(img, [cnt], 0, (0, 0, 255), 2)
-
- cv2.imshow('contours', img)
- cv2.waitKey(0)

使用 cv2.findContours() 寻找轮廓,findContours()有三个参数:输入图像,轮廓检索模式,轮廓近似方法,返回值contours是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy,下边详解 。
图中总共有8条轮廓,2和2a分别表示外层和里层的轮廓,3和3a也是一样。从图中看得出来:
如果我们打印出 cv2.findContours() 函数的返回值hierarchy,会发现它是一个包含4个值的数组:
[Next, Previous, First Child, Parent]
比如2a的父轮廓是2,Parent=2;轮廓2没有父轮廓,所以Parent=-1。
因为没有从属关系,所以轮廓0的下一条是1,1的下一条是2……
图中括号里面1代表外层轮廓,2代表里层轮廓。比如说对于轮廓2,Next就是4,Previous是1,它有里层的轮廓3,所以First Child=3,但因为只有两个层级,它本身就是外层轮廓,所以Parent=-1。大家可以针对其他的轮廓自己验证一下。
CV2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2), abs(y2-y1))<=1。
CV2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
CV2.CHAIN_APPROX_TC89_L1 和 CV2.CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法。
绘制轮廓cv2.drawContours()函数比较简单就不多说了,看上边demo就行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。