python实现轮廓检测与拟合

492 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

最近一直跟Opencv打交道,少不了围着轮廓转圈圈,未来几天会针对轮廓的拟合,面积计算、线性拟合等方法记录一系列的实验过程,今天主要的是针对轮廓的检测与拟合。

轮廓的种类总的来说分为两类:一种是规则形状的,另一类是不具有规则形状的,在实际应用时多数为无规则形状,所以处理起来还是有点恼火的,对于精度要求不高的场景,一般的拟合算法就差不多能够涵盖了,opencv提供了contoursArea()等面积计算函数,所以对于不规则形状的面积计算相比自己造轮子也轻松了不少。废话不多说,下面直接上代码。

上代码之前先附上我自己制作的实验图片,里面包含了有规则与无规则的形状轮廓

testContours.PNG

代码如下:

import cv2
import numpy as np


img_path = '../Images/testContours.PNG'
# 读入图像
img = cv2.imread(img_path)
# 使用现成的轮廓检测函数
edge = cv2.Canny(img, 100, 200)
# 膨胀操作
dilate_img = cv2.dilate(edge, (3, 3), iterations=1)
# 现成函数,查找轮廓
contours, hire = cv2.findContours(dilate_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
    # 计算轮廓坐标
    bbox = cv2.boundingRect(cnt)
    # 绘制矩形
    cv2.rectangle(img, bbox, color=(0, 100, 180), thickness=2)
    # 计算外接矩形的坐标
    rect = cv2.minAreaRect(cnt)
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    # 计算最小外接圆的圆形和半径
    center, radius = cv2.minEnclosingCircle(cnt)
    center = np.array(center).astype(int)
    # 绘制外接圆
    cv2.circle(img, center, int(radius), (0, 255, 0), 2)
    # 绘制最小外接矩形
    cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
# 显示图像
cv2.imshow('img', img)
cv2.waitKey(0)

代码多数部分使用了opencv自带函数,并没有自造轮子

对于上述代码的处理效果如下所示

image.png

五个中,只有两个的外接矩形,但是一般来说不可能出现这样的问题,所以我打印出了矩形的坐标,结果如下

image.png 直观来看,确实没什么问题,坐标既然存在,那肯定是画上去了,所以不甘心的我在不动另外两个绘制轮廓的情况下,对原图的处理后的图像做差分,得到了如下的效果

image.png 因为差分过程中有一部分像素被剪掉了,但是整体的轮廓显现出来了,说明在绘制过程中被别的颜色像素覆盖住了。然后将绘制的另外两个注释掉代码再看,确实跟我们想的一样,验证结束。说明一下,在做背景差分时为了提高对比,将绘制颜色做了调整。

image.png