Canny 算法
边缘:我的理解是在图像处理的过程中,针对我们图像处理的过程中,梯度变化以较大的地方能够让我们能够快速辨识,针对一个人脸,脸上有一些平滑的地方(没错我针对美颜的),与头发的接壤处,会让我们清楚的意识到这个人脸的大小形状等特征。通过线条我们能够很清晰的辨认一个人的特征,因此,图像边缘是图像处理之中很简单的任务之一。
Canny 边缘检测算法是一种广泛使用的边缘检测技术,由 John F. Canny 在 1986 年提出。它被认为是最优的边缘检测算法之一,因其在检测边缘时具有较好的准确性和低噪声敏感性。Canny 算法的主要目标是识别图像中的边缘,并提供精确的边缘定位。
Canny 算法的步骤
Canny 边缘检测算法是一种多阶段的边缘检测方法,其数学原理主要包括以下几个步骤:
1. 高斯平滑
在进行边缘检测之前,首先需要对图像进行平滑处理,以减少噪声的影响。Canny 算法使用高斯滤波器来实现这一点。高斯滤波器的数学表达式为:
G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x, y) = \frac{1}{2\pi\sigma^2} e^{-\frac{x^2 + y^2}{2\sigma^2}} G(x,y)=2πσ21e−2σ2x2+y2
其中, σ \sigma σ 是高斯分布的标准差, ( x , y ) (x, y) (x,y) 是相对于滤波器中心的坐标。通过卷积操作,将高斯滤波器应用于输入图像,得到平滑后的图像。
2. 计算梯度
接下来,使用 Sobel 算子或其他梯度算子计算图像中每个像素的梯度强度和方向。Sobel 算子通常有两个方向的卷积核:
-
水平方向( G x G_x Gx):
G x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] G_x = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} Gx= −1−2−1000121 -
垂直方向( G y G_y Gy):
G y = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] G_y = \begin{bmatrix} 1 & 2 & 1 \\ 0 & 0 & 0 \\ -1 & -2 & -1 \end{bmatrix} Gy= 10−120−210−1
通过卷积操作,计算每个像素的梯度强度 G G G 和方向 θ \theta θ:
G = G x 2 + G y 2 G = \sqrt{G_x^2 + G_y^2} G=Gx2+Gy2
θ = arctan ( G y G x ) \theta = \arctan\left(\frac{G_y}{G_x}\right) θ=arctan(GxGy)
3. 非极大值抑制
在计算出梯度强度和方向后,Canny 算法会进行非极大值抑制,以细化边缘。对于每个像素,算法会检查其梯度强度是否为局部最大值。具体步骤如下:
- 根据梯度方向,将像素分为四个方向( 0 ∘ 0^\circ 0∘、 4 5 ∘ 45^\circ 45∘、 9 0 ∘ 90^\circ 90∘、 13 5 ∘ 135^\circ 135∘)。
- 对于每个像素,检查其在梯度方向上的前后两个像素的强度值。
- 如果当前像素的强度值不是局部最大值,则将其强度设为零。
4. 双阈值处理
Canny 算法使用双阈值处理来确定强边缘和弱边缘。设定两个阈值(高阈值和低阈值):
- 强边缘:梯度强度高于高阈值的像素。
- 弱边缘:梯度强度介于低阈值和高阈值之间的像素。
- 非边缘:梯度强度低于低阈值的像素。
5. 边缘连接
最后,Canny 算法通过连接强边缘和弱边缘来形成最终的边缘图。只有与强边缘相连的弱边缘才会被保留,其他的弱边缘将被抑制。这一过程确保了边缘的连续性。
Canny 边缘检测算法的数学原理结合了高斯平滑、梯度计算、非极大值抑制、双阈值处理和边缘连接等多个步骤。通过这些步骤,Canny 算法能够有效地检测图像中的边缘,并提供较高的准确性和鲁棒性。
Canny 算法的优点
- 高精度:Canny 算法能够准确地检测到边缘,并且对噪声具有较强的鲁棒性。
- 多级阈值:通过双阈值处理,可以有效地分离强边缘和弱边缘,增强边缘的连通性。
- 细化边缘:非极大值抑制步骤使得边缘更加细化,减少了边缘的宽度。
Canny 算法的缺点
- 计算复杂度:相较于其他简单的边缘检测算法(如 Roberts、Sobel),Canny 算法的计算复杂度较高,处理速度较慢。
- 参数选择:高斯滤波器的标准差和双阈值的选择对结果有较大影响,可能需要根据具体应用进行调整。
应用场景
Canny 边缘检测算法广泛应用于计算机视觉和图像处理领域,包括但不限于:
- 物体检测与识别
- 图像分割
- 特征提取
- 机器人视觉
- 医学图像分析
总之,Canny 边缘检测算法因其高效性和准确性,成为了边缘检测领域的经典算法之一。
Canny算法步骤
- 去燥(常用高斯滤波)
任何边缘检测算法都不可能在未经处理的原始数据上很好地工作,使用高斯滤波可以去除常见的噪声。
g σ ( m , n ) = 1 2 π σ 2 e − m 2 + n 2 2 σ 2 ⋅ f ( m , n ) g_\sigma(m, n)=\frac{1}{\sqrt{2 \pi \sigma^2}} e^{-\frac{m^2+n^2}{2 \sigma^2}} \cdot f(m, n) gσ(m,n)=2πσ21e−2σ2m2+n2⋅f(m,n)
・计算梯度大小和方向
梯度的大小和方向往往可以反应图像灰度值的变化和方向, 可以通过点乘一个sobel或其它算子得到不同方向的梯度值。
常见的梯度算子:canny算子,sobel算子,拉普拉斯算子
・沿着梯度方向进行非极大值抑制
- 双边阈值处理
- 低于低阈值的舍弃, 高于阈值的确定为边缘, 在中间的如果与边缘相连接保留,否则舍去。
cv2.Canny
是 OpenCV 中用于执行 Canny 边缘检测的函数。该函数的主要作用是检测图像中的边缘,并返回一个二值图像,其中边缘像素为白色(255),非边缘像素为黑色(0)。
函数原型
edges = cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)
参数说明
-
image (
numpy.ndarray
):- 描述:输入图像,通常是一个灰度图像。Canny 边缘检测算法通常在灰度图像上运行,因此如果输入是彩色图像,需要先将其转换为灰度图像。
-
threshold1 (
int
):- 描述:低阈值,用于边缘连接的第一阈值。该值用于确定强边缘和弱边缘的分界。梯度强度低于此值的像素被认为是非边缘。
-
threshold2 (
int
):- 描述:高阈值,用于边缘连接的第二阈值。该值用于确定强边缘的分界。梯度强度高于此值的像素被认为是强边缘。
-
apertureSize (
int
, 可选):- 描述:Sobel 算子的大小,默认为 3。该参数决定了用于计算图像梯度的 Sobel 算子的大小。可以设置为 1、3、5 或 7。较大的值会导致更平滑的边缘,但可能会丢失一些细节。
-
L2gradient (
bool
, 可选):- 描述:是否使用更精确的 L2 范数来计算梯度。默认为
False
,表示使用 L1 范数。如果设置为True
,则使用 L2 范数,这样可以获得更精确的边缘检测结果。
- 描述:是否使用更精确的 L2 范数来计算梯度。默认为
返回值
- edges (
numpy.ndarray
):- 返回一个二值图像,其中边缘像素为白色(255),非边缘像素为黑色(0)。
cv2.Canny
函数是实现 Canny 边缘检测的主要工具,通过合理设置阈值和其他参数,可以有效地检测图像中的边缘特征。选择合适的阈值和参数对于获得最佳的边缘检测效果至关重要。
import cv2
img = cv2.imread("./images/25.jpg",cv2.IMREAD_COLOR)
cv2.imshow("canny",img)
img = cv2.convertScaleAbs(img,alpha=6,beta=0)
cv2.imshow("abs",img)
# 高斯滤波
img = cv2.GaussianBlur(img,(5,5),1)
canny = cv2.Canny(img,100,150)
canny = cv2.resize(canny,(500,500))
cv2.imshow("Canny",canny)
cv2.waitKey(0)