下一个教程: 轮廓特征
目标
- 理解什么是轮廓线。
- 学习查找轮廓、绘制轮廓等。
- 你将看到这些函数:cv.findContours(), cv.drawContours()
什么是轮廓线?
等高线可以简单地解释为连接所有连续点(沿边界)的曲线,具有相同的颜色或强度。等高线是形状分析和物体检测与识别的一个有用工具。
- 为了获得更好的准确性,使用二进制图像。因此,在寻找轮廓线之前,应用阈值或Canny边缘检测。
- 从OpenCV 3.2开始,findContours()不再修改源图像了。
- 在OpenCV中,寻找轮廓线就像从黑色背景中寻找白色物体。所以请记住,要找到的物体应该是白色的,背景应该是黑色的。
让我们来看看如何找到二进制图像的轮廓线:
import numpy as np
import cv2 as cv
im = cv.imread('test.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
看,在cv.findContours()函数中有三个参数,第一个是源图像,第二个是轮廓检索模式,第三个是轮廓逼近方法。然后它输出轮廓线和层次结构。等高线是一个包含图像中所有等高线的Python列表。每个单独的轮廓线是一个Numpy数组,包含物体边界点的(x,y)坐标。
注意
我们将在后面详细讨论第二个和第三个参数以及层次结构。在那之前,代码样本中给它们的值对所有图像都是有效的。
如何绘制轮廓线?
为了绘制轮廓线,我们使用了cv.drawContours函数。它也可以用来绘制任何形状,只要你有它的边界点。它的第一个参数是源图像,第二个参数是等值线,应该以Python列表的形式传递,第三个参数是轮廓线的索引(在绘制单个轮廓线时很有用。 要绘制所有轮廓线,pass -1),其余参数是颜色、厚度等。
- 绘制图像中的所有轮廓线:
cv.drawContours(img, contours, -1, (0,255,0), 3)
- 要画一个单独的轮廓,比如说第4个轮廓:
cv.drawContours(img, contours, 3, (0,255,0), 3)
- 但在大多数时候,下面的方法会很有用:
cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0,255,0), 3)
注意
后面两种方法是一样的,但是当你继续往下学习时,你会发现最后一种方法更有用。
轮廓逼近方法
这是cv.findContours函数中的第三个参数。它实际上表示什么呢?
上面我们说过,轮廓线是具有相同强度的形状的边界。它存储了一个形状的边界的(x,y)坐标。但它是否存储了所有的坐标?这是由这个轮廓逼近方法指定的。
如果你传递cv.CHAIN_APPROX_NONE,所有的边界点都会被存储。但实际上我们需要所有的点吗?例如,你找到了一条直线的轮廓。你需要这条线上的所有点来表示这条直线吗?不,我们只需要那条线的两个端点。这就是cv.CHAIN_APPROX_SIMPLE的作用。它删除了所有多余的点并压缩了轮廓,从而节省了内存。
下面是一个矩形的图片,演示了这个技术。只要在等高线数组中的所有坐标上画一个圆(用蓝色画)。第一张图片显示了我用cv.CHAIN_APPROX_NONE得到的点(734个点),第二张图片显示了用cv.CHAIN_APPROX_SIMPLE的点(只有4个点)。看,它节省了多少内存!!!!