文章目录
- 前言
- 一、什么是轮廓检测
- 二、轮廓检测与边缘检测的区别
- 三、轮廓检测的过程
前言
之前我们学习了边缘检测算法(如Sobel、Canny等),接下来的课程将会探讨轮廓检测。轮廓检测是图像处理中的一个重要任务,它的目标是识别出图像中的物体轮廓,即物体的外部边界。与边缘检测不同,轮廓检测通常需要对图像进行更复杂的处理,以便有效地提取出物体的整体形状。
一、什么是轮廓检测
轮廓检测是图像处理中的一项任务,其主要目标是在图像中找到物体的外部轮廓,也就是物体的边界。这些轮廓通常被表示为一系列连接的点、线段或曲线,能够描述物体的整体形状。轮廓检测通常应用于目标检测、物体识别、图像分割等领域,是许多计算机视觉应用的重要步骤之一。
二、轮廓检测与边缘检测的区别
在计算机视觉领域中,边缘检测和轮廓检测是两个常用的图像处理任务,它们虽然在一定程度上可以实现相似的目标,但在技术原理和应用场景上有一些区别。
1.边缘检测(Edge Detection):
a.边缘检测旨在检测图像中的边缘,边缘通常表示了图像中灰度值或颜色值的突然变化。
b.边缘检测算法通常会在图像中寻找灰度梯度较大的区域,因为这些区域往往对应着图像中的边缘。
c.常见的边缘检测算法包括Sobel、Prewitt、Canny等,它们可以检测出图像中的强边缘,通常输出的是二值化的图像,其中边缘位置被表示为白色或者其他明显的颜色,而其他部分则是黑色。
2.轮廓检测(Contour Detection):
a.轮廓检测旨在检测图像中的物体轮廓,即物体的外部边界。
b.轮廓检测通常通过将图像分割为不同的区域来实现,然后检测这些区域之间的边界。
c.常见的轮廓检测算法包括基于边缘检测结果的轮廓查找、基于阈值的图像分割算法(如阈值化、分水岭算法等)、基于区域增长的方法等。
d.轮廓检测通常输出的是包含物体外部边界的闭合曲线或者多边形,它们可以用于图像分割、物体识别等任务。
简单的说边缘检测是找出图像中灰度或颜色变化快的地方,通常输出的是边缘的位置信息,用来表示物体的轮廓。轮廓检测则是找出物体的外部轮廓,通常输出的是表示物体形状的闭合曲线或多边形。边缘检测更专注于局部的变化,而轮廓检测则更关注整个物体的外形。
因此,尽管边缘检测和轮廓检测都是图像处理中常用的任务,并且它们在一些方面有着相似之处,但它们的目标和技术方法有所不同,适用于不同的应用场景。
三、轮廓检测的过程
首先我们看一个简单的轮廓检测的代码
import cv2
import numpy as np
# 读取图片
image = cv2.imread('image.jpg')
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用二值化
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 寻找轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 3)
# 显示图片
cv2.imshow('Contours', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
上面的代码可以看到它的流程,在轮廓检测前需要先对图像进行二值化或Canny操作。我们上面代码是使用threshold做了二值化操作。图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓2。threshold的参数127表示 当像素点的值小于127的时候把像素点置于0,当像素点大于127时 置于255,这样就达到吧图片二值化。
二值化过后就可以使用findContours查找轮廓了,我们看下这个方法
contours, hierarchy = cv2.findContours(image, mode, method)
- image:输入的二值化图像,即轮廓检测的源图像,通常为灰度图像经过二值化处理后的图像
- mode:轮廓检索模式,指定轮廓的检索模式,可以是以下值之一:
○ cv2.RETR_EXTERNAL:只检测外部轮廓。
○ cv2.RETR_LIST:检测所有轮廓,不建立等级关系。
○ cv2.RETR_CCOMP:检测所有轮廓,建立两级等级关系。
这种模式下,cv2.findContours() 函数会检测所有轮廓,并将它们组织成两级的等级结构,包括外部轮廓和内部轮廓(可能嵌套多层)。具体来说,当检测到的轮廓之间存在嵌套关系时,外部轮廓被标记为一级轮廓,而内部轮廓被标记为二级轮廓。这种两级等级关系主要用于描述轮廓的包含关系,即一个轮廓是否包含在另一个轮廓内部。例如,假设图像中存在一个外部轮廓和一个内部轮廓,内部轮廓完全包含在外部轮廓内部。在使用 cv2.RETR_CCOMP 模式进行轮廓检测后,返回的轮廓列表中会包含两个轮廓,其中外部轮廓是一级轮廓,内部轮廓是二级轮廓,并且内部轮廓的父轮廓是外部轮廓。总之,建立两级等级关系意味着 cv2.findContours() 函数将轮廓组织成外部轮廓和内部轮廓两个层级,以描述轮廓之间的包含关系。
○ cv2.RETR_TREE:检测所有轮廓,建立完整的等级树结构。 - method:轮廓近似方法,指定轮廓的近似方法,可以是以下值之一:
○ cv2.CHAIN_APPROX_NONE:保存所有的轮廓点。
○ cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角线方向上的所有轮廓,只保留端点。
上面这两个参数是什么区别呢?我们知道线是由点组成,通过CHAIN_APPROX_NONE这个参数可以输出所有的轮廓点,就是一个完整的轮廓,CHAIN_APPROX_SIMPLE 只有端点,比如我们有一个正方形 用第一个参数可以返回正方形的四条线的轮廓,而第二个参数则输出的是正方形的四个点
返回值:
● contours:检测到的轮廓,是一个列表,每个轮廓都是一个 numpy 数组,其中存储了轮廓的所有点坐标。
● hierarchy:轮廓的层级关系,通常在层级轮廓检测时才会用到。
contours得到了轮廓信息,我们就可以去绘制轮廓了,
# 在原始图像上绘制轮廓
image = cv2.drawContours(image, contours, contourIdx, color, thickness)
● image:要绘制轮廓的图像,通常是原始图像的副本。
● contours:要绘制的轮廓列表,是由 cv2.findContours() 函数返回的轮廓信息。
● contourIdx:要绘制的轮廓索引,指定要绘制的轮廓在轮廓列表中的索引。如果设置为负数(例如 -1),则表示绘制所有的轮廓。
● color:绘制轮廓的颜色,可以是 BGR 形式的颜色值,例如 (0, 255, 0) 表示绿色。
● thickness:绘制轮廓的线条宽度,如果设置为负数,则表示填充轮廓内部。默认值为 1,表示绘制轮廓的线条。
返回值:
● 绘制了轮廓的图像。