本文译自https://docs.opencv.org/3.4/d4/d73/tutorial_py_contours_begin.html,原文名:Contours: Getting Started。
目标
- 理解什么是contours
- 学习如何找出contours,绘制contours等
- 相关函数:cv.findContours(), cv.drawContours()
什么是contours?
Contours,即“轮廓”,可以被简单地解释为连结了边界上的所有连续点的曲线。Contours对于形状分析、物体识别和检测非常有用。
注意事项:
- 为了更好的精度,请使用二值图像。因此在找出Contours之前,应该先应用阈值或canny边缘检测
- 从OpenCV 3.2以来,findContours()方法不再修改原始图像而是返回一张被修改的图像作为三个返回参数中的第一个
- 在OpenCV中,找出Contours像是从黑色背景中找出白色物体。因此请记住,物体应该是白色的,背景应该是黑色的
示例如下:
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)
im2, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE., cv.CHAIN_APPROX_SIMPLE)
cv.findContours()方法需要三个参数,第一个是原始图像,第二个是轮廓检索模式,第三个是轮廓近似方法,同时它输出一张修改后的图像(im2)、轮廓(contours)和层次体系(hierarchy)。其中,contours是原图中所有轮廓组成的Python列表。每个单独的轮廓是物体的边界点的(x,y)坐标所组成的Numpy数组。
注意:
- 在OpenCV2中,cv.findContours()的返回值仅有contours和hierarchy两个。
如何绘制Contours
为了绘制Contours,我们使用cv.drawContours,它可以绘制任意形状,只要你提供该形状的边界点(的坐标)。它的第一个参数是原始图像,第二个参数是一个包含所有轮廓(的坐标)的Python列表,第三个参数是轮廓的索引(只有当我们想画单个轮廓时才有用,画所有轮廓的话就传-1)。剩下的参数还有颜色,厚度等等。
示例如下:
# 在一副图像上绘制所有轮廓
cv.drawContours(img, contours, -1, (0, 255, 0), 3)
# 只绘制单个轮廓,比如第四个轮廓(索引从0开始)
cv.drawContours(img, contours, 3, (0, 255, 0), 3)
# 绝大多数时候,以下方法很有用:
cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0, 255, 0), 3)
Contour近似方法
这是cv.findContours()方法的第三个参数。它实际上表示什么呢?
刚才我们说返回的contours中存储了一个形状的边界的(x,y)坐标,但是它需要存储所有坐标吗?这由Contour近似方法来指定。
如果你传递cv.CHAIN_APPROX_NONE,所有的边界点(的坐标)都会被存储。但是在实际中我们真的需要所有的点(的坐标)吗?比如,你想要找出一条直线的轮廓,你需要这条直线上的所有点(的坐标)来表示这条直线吗?事实上我们只需要两个点就够了。这就是cv.CHAIN_APPROX_SIMPLE做的事,它移除了所有冗余的点并且压缩了轮廓,因此节省了内存。
下面这个方框图展示了这项技术。作图展示了cv.CHAIN_APPROX_NONE的结果,右图展示了cv.CHAIN_APPROX_SIMPLE的结果,显而易见,右边这种做法大大节省了内存!