图像轮廓(一)【OpenCV&Python】

本文介绍了使用OpenCV和Python进行图像轮廓查找、绘制及矩特征的计算。重点讲解了cv2.findContours()函数,包括参数解析、轮廓提取方式及轮廓点存储。此外,还探讨了轮廓的绘制、矩特征的计算,如轮廓面积和弧长,并介绍了Hu矩及其在形状匹配中的应用。
摘要由CSDN通过智能技术生成

0 引言

🍔小小搬运工,一边搬运一边思考
参考书籍 《OpenCV轻松入门——面向Python李立宗著,电子工业出版社出版

边缘检测虽然能够检测出轮廓,但边缘是不连续的,检测到的边缘并不是一个整体。图像轮廓是指将边缘连接起来形成的整体,用于后续的计算。

OpenCV提供了查找轮廓的函数cv2.findContours(),该函数能够查找图像轮廓内的信息,而函数cv2.drawContours()函数能够将轮廓绘制出来。

图像轮廓是图像中非常重要的一个特征信息,通过对图像轮廓的操作,我们能够获取目标图像的大小、位置、方向等信息。

1 查找并绘制轮廓

1.1 查找图像轮廓:findContours函数

函数findContours用于查找图像的轮廓,并能够根据参数返回特定方式的轮廓。其语法格式为:

image,contours,hierarchy = cv2.fingContours(image,mode,method)
# 返回值image:与函数参数中的原始图像image一致
# 返回值contours:返回的轮廓
# 返回值hierarchy:图像的拓普信息(轮廓层次)
# 参数image:原始图像。8位单通道图像,所有非零值被处理为1,所有零值保持不变。也就是说灰度图像会被自动处理成二值图像。在实际操作中,可以根据需要,预先使用阈值处理等函数,将待查找轮廓的图像处理为二值图像。
# mode:轮廓检索方式
# method:轮廓的近似方法

1、返回值image

在OpenCV 4.X中,函数cv2.findContours()仅有两个返回值,其语法格式为:

contours,hierarchy = cv2.findContours(image,mode,method)

2、返回值contours

该返回值返回的是一组轮廓信息,每个轮廓都是由若干个点所构成的。例如,contour是[i]是第i个轮廓(下标从0开始),contours[i][j]是第i个轮廓内的第j个点。
(1)type属性

print(type(contours)) # 获取轮廓contours的类型
print(type(contours[0])) # 获取轮廓contours中每个元素的类型

(2)轮廓的个数

print(len(contours))  # 获取轮廓的个数

(3)每个轮廓的点数

print(len(contours[0])) # 打印第0个轮廓的长度(点的个数)
print(contours[0].shape) # 获取轮廓每个轮廓内点的shape属性

(4)轮廓内的点

print (contours[0]) # 打印第0个轮廓中的像素点

3、返回值hierarchy

图像内的轮廓位于不同的位置,将外部的轮廓称为父轮廓,内部的轮廓称为子轮廓。这样,一幅图像的轮廓就建立了父子关系。上述关系就被称为层次(组织结构)。

print(hierarchy) # 查看hierarchy的值,轮廓的层次结构由参数mode决定
[Next,Previous,First_Child,Parant] # 四个元素说明当前轮廓的层次关系
# Next:后一个轮廓的索引编号
# Previous:前一个轮廓的索引编号
# First_Child:第1个子轮廓的索引编号
# Parant:父轮廓的索引编号

如果上述参数所对应的关系为空时,则将该参数所对应的值设为"1"。

4、参数image

原始图像。8位单通道图像,所有非零值被处理为1,所有零值保持不变。也就是说灰度图像会被自动处理成二值图像。在实际操作中,可以根据需要,预先使用阈值处理等函数,将待查找轮廓的图像处理为二值图像。

5、参数mode

参数mode决定了轮廓的提取方式,具体有如下4种:
(1)cv2.RETR_EXTERNAL:只检测外轮廓
(2)cv2.RETR_LIST:对检测到的轮廓不建立等级关系
(3)cv2.RETR_CCOMP:检索所有轮廓并将它们组织成两级层次结构
(4)cv2.RETR_TREE:建立一个等级树的结构

6、参数method

参数method决定了如何表达轮廓,具体如下:
(1)cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,相邻两个像素位置差不超过1。
(2)cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标。例如,在极端的情况下,一个矩形只需要用4个点来保存轮廓信息。
(3)cv2.CHAIN_APPROX_TC89_L1:使用teh-Chinl chain近似算法的一种风格。
(4)cv2.CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain近似算法的一种风格。
注意:
待处理的源图像必须是灰度二值图。因此,在通常情况下,都要预先对图像进行阈值分割或者边缘检测,得到满意的二值图像后再将其作为参数使用。
在OpenCV中,都是从黑色背景中查找白色对象。因此,对象必须是白色的,背景必须是黑色的。

1.2 绘制图像轮廓:drawContours函数

在OpenCV中,可以使用函数cv2.drawContours()绘制图像轮廓。该函数的语法格式是:

image = cv2.drawContours(
image,
contours,
contourIdx,
color[,
thickness[,
lineType[,
hierarchy[,
maxLevel[,
offset]]]]])
# 返回值image表示目标图像,即绘制了边缘的原始图像。
# 参数image:待绘制轮廓的图像。函数cv2.drawContours会在图像image上直接绘制轮廓,若有其他用途,需要预先复制一份,将该副本图像传递给函数cv2.drawContours()使用。
# 参数contours:需要绘制的轮廓。该参数的类型与函数cv2.findContours()的输出contours相同,都是list类型。
# 参数contourIdx:需要绘制的边缘索引,告诉函数cv2.drawContours()要绘制某一条轮廓还是全部轮廓。如果该参数是一个整数或者为0,则表示绘制对应索引号的轮廓;如果该值为负值(-1),则表示绘制全部轮廓。
# 参数color:绘制的颜色,用BGR格式表示。
# thickness:可选参数,表示绘制轮廓时所用画笔的粗细,如将该值设置为"-1",则表示要绘制实心轮廓。
# lineType:可选参数,表示绘制轮廓时所用的线型。
# hierarchy:对应函数cv2.findContours()所输出的层次信息。
# maxLevel:控制所控制的轮廓层次的深度。如果值为0,表示仅仅绘制第0层的轮廓;如果值为其他的非零正数,表示绘制最高层及以下的相同数量层级的轮廓。
# offset: 偏移参数。该参数使轮廓偏移到不同的位置展示出来。

1.3 轮廓实例

例1:绘制一幅图像内的所有轮廓。
将cv2.drawContours()的参数contourIdx的值设置为“-1”。

import cv2
o = cv2.imread("C:\\Users\\Kris\\Desktop\\timg.jpg")
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) 
ret,binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # 根据版本确定是否返回image
o = cv2.drawContours(o,contours,-1,(0,0,255),5) 
# -1代表轮廓索引,BGR(0,255,255)代表红色,5代表参数thickness的轮廓粗细
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()  

运行程序,结果显示如下。
在这里插入图片描述

例2:逐个显示一幅图像内的边缘信息。
将cv2.drawContours()的参数contourIdx的值设置为具体的索引值。

import cv2
import numpy as np
o = cv2.imread("C:\\Users\\Kris\\Desktop\\timg.jpg")
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY) 
ret,binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
n = len(contours)
con
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值