9. 图像轮廓

1.了解什么是轮廓。

学习寻找轮廓,绘制轮廓等
了解这些函数:cv.findContours(), cv.drawContours()
轮廓可以简单地解释为连接所有连续点(沿边界)的曲线,具有相同的颜色或强度。轮廓是形状分析和对象检测和识别的有用工具。
为了获得更好的准确性,请使用二进制图像。所以在找到轮廓之前,应用阈值或精明的边缘检测。

从 OpenCV 3.2 开始, findContours() 不再修改源图像。
在 OpenCV 中,寻找轮廓就像从黑色背景中寻找白色物体。所以请记住,要找到的对象应该是白色的,背景应该是黑色的。
a. findContours()Python中用法:

contours, hierarchy	=	cv.findContours(	image, mode, method[, contours[, hierarchy[, offset]]]	)
参数描述
src源,8 位单通道图像。非零像素被视为 1。零像素保持 0,因此图像被视为二值图。您可以使用 compare、inRange、threshold、adaptiveThreshold、Canny 和其他方法从灰度或彩色图像中创建二值图像。如果 mode 等于 RETR_CCOMP 或 RETR_FLOODFILL,则输入也可以是标签的 32 位整数图像 (CV_32SC1)。
contours检测到的轮廓。每个轮廓都存储为一个点向量(例如 std::vector<std::vectorcv::Point >)。
hierarchy可选的输出向量(例如 std::vectorcv::Vec4i),包含有关图像拓扑的信息。它的元素与轮廓的数量一样多。对于每个第 i 个轮廓轮廓[i],将元素hierarchy[i][0]、hierarchy[i][1]、hierarchy[i][2]和hierarchy[i][3]设置为0-基于相同层次级别的下一个和前一个轮廓的轮廓中的索引,分别是第一个子轮廓和父轮廓。如果轮廓 i 没有下一个、上一个、父级或嵌套轮廓,则hierarchy[i] 的相应元素将为负
dx导数x的阶数
dy导数y的阶数
mode轮廓检索模式,见RetrievalModes
method轮廓近似方法,见ContourApproximationModes
offset每个轮廓点移动的可选偏移量。如果轮廓是从图像 ROI 中提取的,然后应该在整个图像上下文中对其进行分析,这将非常有用。

findContours() 重载函数
python中用法:

contours, hierarchy	=	cv.findContours(	image, mode, method[, contours[, hierarchy[, offset]]]	)

这是一个重载的成员函数,为方便起见而提供。它与上述函数的不同之处仅在于它接受的参数。


b. drawContours()python中用法:

	image	=	cv.drawContours(	image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]	)
参数描述
image目标图像
contours所有输入轮廓。每个轮廓都存储为一个点向量。
contourIdx指示要绘制的轮廓的参数。如果为负,则绘制所有轮廓。
color轮廓的颜色。
thickness绘制轮廓线的厚度。如果它是负数(例如,thickness=FILLED),则绘制轮廓内部。
lineType线路连接。请参阅线型lineTypes
hierarchy有关层次结构的可选信息。仅当您只想绘制一些轮廓时才需要它(请参阅 maxLevel )。
maxLevel绘制轮廓的最大级别。如果为 0,则仅绘制指定的轮廓。如果为 1,则该函数绘制等高线和所有嵌套的等高线。如果为 2,则函数绘制轮廓、所有嵌套轮廓、所有嵌套到嵌套轮廓,依此类推。仅当有可用的层次结构时才考虑此参数。
offset可选的轮廓移位参数。将所有绘制的轮廓移动指定的 o f f s e t = ( d x , d y ) offset=(dx,dy) offset=(dx,dy)

2. 绘制轮廓

  1. 绘制图像中的所有轮廓
cv.drawContours(img, contours, -1, (0,255,0), 3)
  1. 要绘制单个轮廓,比如第 4 个轮廓:
cv.drawContours(img, contours, 3, (0,255,0), 3)
  1. 但大多数时候,下面的方法会很有用:
cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0,255,0), 3)

实例

img = cv.imread("../../file/photos/box.png")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) #将图像转换为灰度图像
print(img.dtype)
ret, th = cv.threshold(gray, 55, 255, 0) #  对图像进行二值处理
#获取边缘轮廓列表
contours, hierarchy = cv.findContours(th, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

# cnt = contours[0]
# img = cv.cvtColor(img, cv.COLOR_GRAY2RGB)
img_contour = cv.drawContours(img, contours, -1, (0, 255, 0), 3) #在原图上画出轮廓
plt.subplot(121), plt.imshow(th, 'gray'), plt.title("Oringal")
plt.axis('off')#关闭坐标轴
plt.subplot(122), plt.imshow(img_contour, ), plt.title("img_contour")
plt.axis('off')

plt.show()

结果:
在这里插入图片描述

Contour Approximation Method

这是 cv.findContours 函数中的第三个参数。它实际上表示什么?
上面,我们说过轮廓是具有相同强度的形状的边界。它存储形状边界的 (x,y) 坐标。但它是否存储了所有坐标?这是由这种轮廓近似方法指定的。
如果传递 cv.CHAIN_APPROX_NONE,则存储所有边界点。但实际上我们需要所有的点吗?例如,您找到了一条直线的轮廓。你需要线上的所有点来代表那条线吗?不,我们只需要那条线的两个端点。这就是 cv.CHAIN_APPROX_SIMPLE 所做的。它去除所有冗余点并压缩轮廓,从而节省内存。
下面的矩形图像演示了这种技术。只需在轮廓数组中的所有坐标上绘制一个圆圈(以蓝色绘制)。第一张图显示了我用 cv.CHAIN_APPROX_NONE(734 点)得到的点,第二张图显示了用 cv.CHAIN_APPROX_SIMPLE 得到的点(只有 4 点)。看,它节省了多少内存!!!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值