一、什么是轮廓
轮廓可以简单地解释为连接所有连续点(沿着边界),具有相同颜色或强度的曲线。轮廓是形状分析和物体检测和识别的有用工具。
• 为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者 Canny 边界检测。
• 查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图像的话,应该将原始图像存储到其他变量中。
• 在 OpenCV 中,查找轮廓就像在黑色背景中超白色物体。你应该记住, 要找的物体应该是白色而背景应该是黑色。
二、如何在一个二值图像中查找轮廓:
import numpy as np import cv2 img = cv2.imread('F:/rectangle.jpg') imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(imgray,127,255,0) contours, hierachy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
函数 cv2.findContours() 有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。这个参数如果被设置为 cv2.CHAIN_APPROX_NONE,所有的边界点 都会被存储。但是我们真的需要这么多点吗?例如,当我们找的边界是一条直 线时。你用需要直线上所有的点来表示直线吗?不是的,我们只需要这条直线 的两个端点而已。这就是 cv2.CHAIN_APPROX_SIMPLE 要做的。它会将轮廓上的冗余点都去掉,压缩轮廓,从而节省内存开支。
返回值有三个,第一个是图像,第二个是轮廓,第三个是(轮廓的)层析结构,官方给的也是三个,但是自己实践的情况是两个返回值,没有第一个,也可能是编辑器的问题,目前还没有在别的平台试过,如果试过可能会自己删除这一句话。轮廓(第二个返回值)是一个 Python 列表,其中存储这图像中的所有轮廓。每一个轮廓都是一个 Numpy 数组,包含对象边界点(x,y)的坐标。
三、绘制轮廓
函数 cv2.drawContours() 可以被用来绘制轮廓。它可以根据你提供 的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一 个 Python 列表。第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设 置为 -1 时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度等。
cv2.drawContours(img, contours, -1, (0,255,0), 3) #绘制边缘 cv2.imshow('img',img) cv2.waitKey() cv2.destroyAllWindows()
官方给的结果是:第一个图显示使用 cv2.CHAIN_APPROX_NONE 的效果, 一共 734 个点。第二个图是使用 cv2.CHAIN_APPROX_SIMPLE 的结 果,只有 4 个点。
实践结果确实只有一种情况: cv2.CHAIN_APPROX_NONE()和cv2.CHAIN_APPROX_SIMPLE()效果一样。
拓展:
自己写的程序:
#coding:utf-8 import numpy as np import cv2 img = cv2.imread('F:/manyRec.jpg') imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(imgray,127,255,0) contours, hierachy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for i in range(int(len(contours))): #绘制几个形状的边缘 cnt = contours[i] cv2.drawContours(img, [cnt], -1, (i*40, 255-i*40, 255-i*40), 3) #用不同的颜色 cv2.imshow('img',img) cv2.waitKey() cv2.destroyAllWindows()
效果图: