opencv两个图像相减_新视界-OpenCV教程(18)- 轮廓:开端

a30423184608b0132248038bed320f6a.png

新视界-OpenCV教程系列文章

新视界-OpenCV教程(1)-入门介绍

OpenCV 中的图形用户界面特征系列

新视界-OpenCV教程(2)-图片入门

新视界-OpenCV教程(3)-视频入门

新视界-OpenCV教程(4)- 绘图功能

新视界-OpenCV教程(5)- 鼠标的画笔功能

新视界-OpenCV教程(6)- 作为调色板的轨迹栏

核心操作系列

新视界-OpenCV教程(7)- 对图片的基本操作

新视界-OpenCV教程(8)- 图像运算

新视界-OpenCV教程(9)- 性能测量和改进技术

OpenCV 中的图像处理系列

新视界-OpenCV教程(10)- 改变颜色空间

新视界-OpenCV教程(11)- 图像阈值

新视界-OpenCV教程(12)- 图像的几何变换

新视界-OpenCV教程(13)- 平滑图像

新视界-OpenCV教程(14)- 形态变换

新视界-OpenCV教程(15)- 图像梯度

新视界-OpenCV教程(16)- Canny 边缘检测

新视界-OpenCV教程(17)- 图像金字塔

本文目标

理解什么是轮廓,轮廓系列会分为5篇文章一一详细讲解。这是第一篇。

学会如何找到轮廓,画出轮廓。

我们会看到这些函数:cv2.findContours (), cv2.drawContours ()

d879e787039470670848c3e391b89480.png

什么是轮廓?

轮廓可以简单地解释为一条连接所有连续点 (沿着边界)并具有相同颜色或强度的曲线。轮廓是形状分析和目标检测与识别的重要工具。

  • 为了更好的准确性,我们将使用二进制图像。因此,在找到轮廓之前,我们需要应用阈值或canny边缘检测。
  • findContours 函数可以用来修改源图像。如果我们在找到轮廓之后还想要源图像,要确保在使用函数前,把原图像信息存储到其他变量中。
  • 在OpenCV 中,寻找轮廓就像从黑色背景中寻找白色的物体。记住,要找的对象应该是白色的,而背景应该是黑色的。

让我们看看下面的代码如何找到一个二进制图像的轮廓:

# 导入包
import numpy as np
import cv2

# 读取图片
im = cv2.imread('test.jpg')
# 转换成灰度图像
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
# 设置阈值
ret,thresh = cv2.threshold(imgray,127,255,0)
# 用函数找到图像的轮廓,下面会详介
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

从上面的代码可见,cv2.findContours() 函数中有三个参数,第一个是源图像,第二个是轮廓的检索模式,第三个是轮廓的近似方法。它依次输出图像,轮廓和层次结构。这里的contours 轮廓是图像中所有轮廓的Python 列表。每个单独的轮廓是物体的边界点的坐标(x,y) 的Numpy 数组。

请注意:我们会在后面详细讨论第二个和第三个参数以及关于层次结构的内容。在此之前,代码示例中给出的值对所有图像都适用。

如何画轮廓?

如果想画出轮廓,cv2.drawContours 函数就得使用。只要我们有任何想画的形状的边界点,该函数也可以用来绘制任何我们想要的形状。它的第一个参数是源图像,第二个参数是应该作为Python 列表传递的轮廓,第三个参数是轮廓的索引(这在我们绘制单个轮廓时很有用,如果要绘制所有的轮廓,传递-1即可),而剩余的参数则是颜色,厚度等。

在图像中画出所有的轮廓的代码:

img = cv2.drawContours(img, contours, -1, (0,255,0), 3) # 这里的-1 是关键,说明我们要全部的轮廓

如果我们只想要单独特定的轮廓,比如说第4个轮廓,代码如下:

img = cv2.drawContours(img, contours, 3, (0,255,0), 3) # 这里的3 是关键,因为计算机中0是第一个,3就代表第四个

但是多数情况,下面的代码是很有帮助的,代码如下:

cnt = contours[4]
img = cv2.drawContours(img, [cnt], 0, (0,255,0), 3)

请注意:最后两个方法的效果是相同的,但是当我们继续学下去之后,就将看到最后一个方法更有用。

轮廓近似法

轮廓近似法 Contour Approximation Method,这是cv2.findContours 函数中的第三个参数。但它实际上表示什么呢?

在文章前面,我们说过轮廓是具有相同强度的形状的边界。它存储形状边界的(x,y) 坐标。但是它是否能存储所有的坐标?这则是由轮廓近似法确定的。

如果我们在近似法中传递了cv2.CHAIN_APPROX_NONE(我们在第一个代码中所使用的),那么函数将存储所有边界点。但实际上我们经常需要所有的点吗?例如,当我们想了解一条直线的轮廓,我们需要这条直线上的所有点来表示这条直线吗?显然不是,我们只需要这条线的两个端点即可。这就是cv2.CHAIN_APPROX_SIMPLE 所表达的。它将去除所有冗余点,压缩轮廓,以此来节省内存。

下面的矩形图像演示了这种技术的原理。在等高线阵列的所有坐标上画一个小圆(用蓝色画,所有的小圆连起来就是线),第一幅图展示了我用cv2.CHAIN_APPROX_NONE(734个点) 得到的所有的点,第二张图显示的是用cv2.CHAIN_APPROX_SIMPLE(只有4个点) 得到的图像。很明显,它节省了很多内存!!!

5a3970df40a319f4e00594910db37c3d.png
734个点 VS 4个点

在下一篇文章中,将着重讲的是新视界-OpenCV教程(19)- 轮廓:特征。

如果你觉得我的文章有用,顺手点个赞,关注下我的专栏或则留下你的评论吧!

d372e0cd350a05d2248aa1cb25d50eb4.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值