0.什么是轮廓
轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。
- 为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者Canny 边界检测。
- 查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他变量中。
- 在OpenCV 中,查找轮廓的原理如下:对于一幅背景为黑色、目标为白色的二值图像,如果在图中找到一个白色点,且它的8邻域(或4邻域)也均为白色,则说明该点是目标的内部点,将其置为黑色,视觉上就像内部被掏空一样;否则保持白色不变,该点是目标的边界点。
- 边缘检测和轮廓提取的区别:
- 边缘检测主要是通过一些手段检测数字图像中明暗变化剧烈(即梯度变化比较大)像素点,偏向于图像中像素点的变化。如canny边缘检测,结果通常保存在和源图片一样尺寸和类型的边缘图中。
- 轮廓检测指检测图像中的对象边界,更偏向于关注上层语义对象。如OpenCV中的findContours()函数, 它会得到每一个轮廓并以点向量方式存储,除此也得到一个图像的拓扑信息,即一个轮廓的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的索引编号。
- 搬几张图来解释一下(来源):以下的图分别为灰度图、边缘图、轮廓图
1.查找并绘制轮廓
代码速记:
- cv2.findContours()
- cv2.drawContours()
参数解释:
#二值图像、轮廓检索模式(看本文第5条)、轮廓近似方法
image,contours,hierarchy=cv2.findContours(thresh_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#原图、轮廓、轮廓索引、颜色、thickness
img1=cv2.drawContours(self.img,contours,-1,(0,255,0),3)
- 函数cv2.findContours() 返回值有三个:图像、轮廓、(轮廓的)层析结构
- 轮廓(第二个返回值)是一个Python列表,其中存储这图像中的所有轮廓。每一个轮廓都是一个Numpy 数组,包含对象边界点(x,y)的坐标
实战:
def draw(self):
#【1】把图像变灰,再二值化
gray=cv2.cvtColor(self.img,cv2.COLOR_BGR2GRAY)
ret,thresh_img=cv2.threshold(gray,127,255,0)
#【2】寻找轮廓:会改变原始图像
image,contours,hierarchy=cv2.findContours(thresh_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#retr_tree,chain_approx_simple
#【3】绘制所有轮廓
img1=cv2.drawContours(self.img,contours,-1,(0,255,0),3)
#【4】绘制索引为1的轮廓
img2=cv2.drawContours(self.img,contours,1,(0,255,0),3)
titles = ['all', 'one']
imgs = [img1, img2]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(cv2.cvtColor(imgs[i],cv2.COLOR_BGR2RGB))
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
2.轮廓特征
代码速记:
- cv2.moments():计算图像的中心矩(关于矩的知识)
- cv2.contourArea():计算轮廓区域的面积
- cv2.arcLength():计算轮廓长度
- cv2.approxPolyDP():逼近多边形曲线
- cv2.convexHull():提取轮廓凸包
- cv2.isContourConvex():测试轮廓的凸性
- cv2.boundingRect():轮廓的外包矩形
- cv2.minAreaRect():轮廓的最小外包矩形(考虑旋转)
- cv2.minEnclosingCircle():轮廓的最小外包圆
- cv2.fitEllipse():用椭圆拟合轮廓
- cv2.fitLine():用直线拟合轮廓
实战:
def features(self):
#【0】检测图像轮廓
img = cv2.imread('../images/test2.jpg',0)
cimg=cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)#后面画图必须用三通道图像
ret,thresh = cv2.threshold(img,127,255,