Python+OpenCV之图像轮廓详解
本文详细解析OpenCV中图像轮廓的提取、绘制及特征计算方法。涵盖findContours函数的检索模式与逼近方法,演示如何绘制指定索引轮廓,并深入讲解面积、周长、边界矩形及外接圆等几何特征的获取与计算,提供完整的Python代码示例。
1. 图像轮廓
1.1 findContours介绍
cv2.findContours(img, mode, method)
mode参数用于指定轮廓检索模式,决定如何构建轮廓层级结构。
- RETR_EXTERNAL:仅检索最外层的轮廓,忽略内部嵌套关系;
- RETR_LIST:检索所有轮廓,并将它们存储在一个扁平的列表中,不建立层级关系;
- RETR_CCOMP:检索所有轮廓,并将它们组织为两层结构:第一层为各部分的外部边界,第二层为内部空洞的边界;
- RETR_TREE:检索所有轮廓,并重构嵌套轮廓的完整层级树状结构;
method参数用于指定轮廓逼近方法,决定如何存储轮廓点的坐标信息。
- CHAIN_APPROX_NONE:以Freeman链码的形式输出所有轮廓点,不进行任何压缩;其他方法则输出多边形顶点序列。
- CHAIN_APPROX_SIMPLE:压缩水平、垂直和倾斜部分的轮廓,仅保留终点坐标,从而减少数据量并提高处理效率。
1.2 绘制轮廓
import cv2
def cv_show(img, name):
cv2.imshow(name, img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('DataPreprocessing/img/contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh, 'thresh')
contours.png原图展示:

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res, 'res')
在绘制轮廓时,参数“-1”表示显示所有检测到的轮廓。颜色设置采用(B, G, R) = (0, 0, 255),即红色,用于高亮显示全部轮廓,效果如下所示:

或者仅显示索引为1的特定轮廓,具体代码如下:
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 1, (0, 0, 255), 2)
cv_show(res, 'res')
在上述示例中,索引为1的轮廓对应三角形的内部轮廓,而索引0对应最外层的外轮廓。

1.3 轮廓特征
cnt = contours[0]
# 面积
print("面积: ", cv2.contourArea(cnt))
# 周长,True表示闭合的
print("周长: ", cv2.arcLength(cnt, True))
输出结果如下:
面积: 8500.5 周长: 437.9482651948929
2. 轮廓近似
2.1 轮廓
contours2.png原图 :

img = cv2.imread('DataPreprocessing/img/contours2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
draw_img = img.copy()
res = cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2)
cv_show(res, 'res')
边缘检测:

原理说明:以一条弧线为例,连接其端点A和B形成线段AB。在弧线上选取一点C,计算C到线段AB的最大距离d1。若d1不小于预设阈值T,则以A和C为端点连接线段AC,并重复上述操作,计算新线段上的最大距离d2并与T比较,直至某段距离dn小于阈值T,此时该线段即为轮廓边缘的一部分。

2.2 边界矩形
img = cv2.imread('DataPreprocessing/img/contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]
x, y, w, h = cv2.boundingRect(cnt)
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv_show(img, 'img')

2.3 外界多边形及面积
area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area) / rect_area
print('轮廓面积与边界矩形比', extent)
输出结果如下:
轮廓面积与边界矩形比 0.5154317244724715
外接圆形:
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
cv_show(img, 'img')
结果展示:

到此这篇关于Python+OpenCV之图像轮廓详解的文章就介绍到这了,更多相关Python OpenCV图像轮廓内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













