边缘检测虽然能检测出边缘,但边缘是不连续的,并不是一个整体。图像轮廓是将边缘连接起来形成的一个整体,用于后续的计算。图像轮廓是图像中非常重要的一个特征信息,通过图像轮廓的操作,可以获取目标图像的大小、位置、方向等信息。
cv2.findContours()函数可以查找图像内的轮廓信息,而cv2.drawContours()能够将轮廓绘制出来。
1.查找并绘制图像轮廓
返回值image: 与函数参数中的图像image一致。在OpenCV 4.X中,该返回值已经被取消;
返回值contours: 返回的轮廓。是list类型,每个元素都是一个轮廓的信息,由此可以知道每个轮廓点的个数和位置。list的长度反映了轮廓的个数。
hierachy: 图像的拓扑信息(轮廓层次)。记录轮廓与轮廓之间的关系,每个轮廓(Contours列表的子元素)对应一个四个元素来说明当前轮廓的层次关系([next,Previous,First_child,parent])。轮廓的层次结构是由mode参数决定的。不同的mode得到的轮廓编号不一样,hierachy也不一样。
方法的参数:
image:原始图像。8位单通道图像,所有非零值被处理为1,所有零值保持不变。也就是灰度图会被自动处理为二值图像。我们通常可以用阈值处理等函数将待查轮廓的图像处理为二值图像。
mode: 轮廓检索模式。决定了轮廓的提取方式,具体有四种:cv2.RETR_EXTERNAL,只检测外轮廓;cv2.RETR_LIST,对检测到的轮廓不建立等级关系;cv2.RETR_CCOMP,检测所有轮廓并将它们组织成两级层次结构,上面一层为外边界,下面一层为内孔的边界。如果内孔内还有一个连通的物体,则这个物体的边界仍然位于顶层;cv2.RETR_TREE,建立一个等级树结构的轮廓。
method: 轮廓的近似方法。决定了如何表达轮廓,可以为如下值:
CV2.CHAIN_APPROX_NONE:储存所有的轮廓点,相邻两个点的像素位置差不超过1;
CV2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标(例如极端情况下可以用四个点保存轮廓信息);
CV2.CHAIN_APPROX_TC89_L1:使用tehCHINl chain近似算法的一种风格;
CV2.CHAIN_APPROX_TC89_KCOS:使用tehCHINl chain近似算法的一种风格。
2.绘制图像轮廓
在OpenCV中,可以使用函数cv2.drawContours()
参数:
image: 待绘制轮廓的图像。要注意,该函数会在图像image的基础上绘制轮廓,所以这里最好用原始图像的备份,以免改变原始图像。
contours: 需要绘制的轮廓,该参数类型与findContours()输出的contours相同,都是list;
contourIdx: 需要绘制的边缘索引,告诉该函数绘制那一条轮廓。若参数为负数(通常是-1),则表示绘制所有轮廓;
color: 绘制的颜色,用BGR表示;
thickness: j可选参数,表示绘制轮廓的画笔的粗细。如将该值设置为-1,则表示要绘制实心轮廓;
lineType: 可选参数,表示绘制轮廓时所用的线型
hierarchy: 对应函数cv2.findContours()输出的层次信息;
maxLevel:控制所绘制的轮廓层次的深度。如果值为0,表示仅绘制第0层德轮廓;如果为其他非零正数,表示绘制最高层及以下的相同数量层级的轮廓;
offset:偏移参数。该参数使轮廓偏移到不同位置展示出来。
3.实例
1)提取并绘制图像轮廓·:
2)使用轮廓绘制功能,提取前景·对象:
将contourIdx 设置为2,提取编号为2的轮廓;thickness设置为-1,将轮廓填充为实心,颜色为(255,255,255)。之后将mask与原图像进行一次与或按位运算,得到前景: