本文主要是介绍Sobel边缘检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
声明:学习过程中的知识总结,欢迎批评指正。
基本原理
- 灰度处理:边缘检测是基于图像亮度变化实现的,而图像的亮度信息通过灰度图像体现,因此需要把彩色图像转换成灰度图像。
- 平滑处理:可以使用高斯滤波等滤波算法将图像中的噪声去除,使图像的信息更加纯粹,便于检测边缘信息。
- 计算梯度:使用Sobel算子计算图像的梯度,包括水平方向的算子Gx和垂直方向的算子Gy,分别用于检测水平方向和垂直方向的边缘。
- 计算梯度幅度和方向:对于每个像素,根据其水平方向和垂直方向的梯度值,计算梯度幅度和方向。梯度幅度通常使用以下公式计算:,梯度方向通常使用以下公式计算:
- 非极大值抑制:为了得到细的边缘,使用非极大值抑制处理梯度幅度图像。对于每个像素,如果其梯度幅度不是其邻域内沿梯度方向的最大值,则将其梯度幅度设为0。
- 双阈值处理:为了分离出真正的边缘,使用双阈值处理梯度幅度图像。选择两个阈值:高阈值和低阈值。对于每个像素,如果其梯度幅度大于高阈值,则认为它是边缘;如果其梯度幅度小于低阈值,则认为它不是边缘;如果其梯度幅度在两个阈值之间,则只有当它连接到一个边缘像素时,才认为它是边缘。
具体实现过程
灰度处理
不同的标准对应的RGB转灰度公式是不一样的,这里选用NTSC(National Television System Committee, 美国国家电视系统委员会)标准中的RGB888转YCbCr公式,这是目前中国乃至世界范围内使用最广泛的标准,具体公式如下:
Y = 0.299R +0.587G + 0.114B
Cb = 0.568(B-Y) + 128 = -0.172R-0.339G + 0.511B + 128
CR = 0.713(R-Y) + 128 = 0.511R-0.428G -0.083B + 128
由于FPGA无法处理浮点数,所以通过加法和移位来实现这一过程,具体公式如下:
Y = (77 R + 150G + 29 *B)>>8
Cb = (-43*R - 85 G + 128B)>>8 + 128
Cr = (128R - 107G - 21 *B)>>8 + 128
Y = (77 R + 150G + 29 *B )>>8
Cb = (-43*R - 85 G + 128B + 32768)>>8
Cr = (128R - 107G - 21 *B + 32768)>>8
平滑处理
对于图像的滤波有均值滤波、中值滤波和高斯滤波等多种滤波方式,其主要目的是增强图像的某些特性或消除某些不需要的信息。基本上都可以理解成是通过卷积实现的,这里以高斯滤波为例。
将图像中每个像素的颜色值替换为其邻域内像素颜色值的加权平均。这个权重由高斯函数决定,距离中心像素越近的像素权重越大,距离中心像素越远的像素权重越小。这样可以保证中心像素的颜色值最大程度地保留下来,而周围像素的颜色值则对其有所影响,从而达到模糊的效果。在实际应用中,通常会选择一个大小为 𝑛×𝑛 的窗口(其中 𝑛n是奇数),然后计算窗口内每个位置的高斯权重,形成一个高斯核。然后,这个高斯核会在图像上滑动,对每个像素及其邻域进行卷积操作,得到模糊后的图像。其中高斯核,是利用 高斯函数 生成的,3×3高斯核生成过程如下:
卷积的实现过程如下:
这里借用其他博主的gif显示动画,有水印。
梯度值和方向计算
使用Gx和Gy两个卷积核分别对图像进行卷积,分别得出横向及纵向的亮度差分近似值,卷积过程与上面描述的高斯滤波卷积过程类似,不赘述。
关于梯度值的计算,在FPGA中乘法和开方消耗硬件逻辑资源较多,因此通常采用绝对值求和进行代替,即|G|=|Gx|+|Gy|。
关于梯度方向的计算,在FPGA中通过Cordic模块或者ip核进行实现,即通过移位和加法的操作实现角度计算。
非极大值抑制
非极大值抑制(Non-Maximum Suppression,简称NMS)是边缘检测中的一个重要步骤,它的主要目的是将边缘细化,即减少边缘的宽度。
在进行边缘检测时,检测出的边缘通常不是一个像素的宽度,而是有一定宽度的。这是因为实际的图像边缘往往并不是理想的锐利边缘,而是在过渡区域内灰度值发生渐变,因此检测出的边缘会有一定的宽度。非极大值抑制的目的就是为了解决这个问题。它的基本思想是在边缘检测得到的梯度图像中,对每一个像素,检查其是否是其所在梯度方向上的局部最大值。如果是,则保留;如果不是,则将其值抑制(通常设置为0),从而实现边缘的细化。
来自chatgpt4的举例:
双阈值处理
在进行了梯度计算和非极大值抑制后,我们得到的边缘图像可能还包含一些噪声和不明显的边缘。为了只保留真正的边缘并去除噪声,我们需要进行双阈值处理。
双阈值处理的思想是设置两个阈值:高阈值和低阈值。对于梯度幅度图像中的每一个像素:
- 如果像素的强度大于高阈值,那么我们认为它是一个强边缘像素,直接标记为边缘。
- 如果像素的强度小于低阈值,那么我们认为它不是边缘,将其抑制(通常设置为0)。
- 如果像素的强度在两个阈值之间,我们则将其标记为弱边缘像素。这些像素可能是边缘,也可能是噪声。为了确定它们是否真正是边缘,我们会检查它们的邻域。如果弱边缘像素的邻域内有强边缘像素,我们就认为这个弱边缘像素是真正的边缘,因为它可能是边缘的一部分。否则,我们将其抑制。
这篇关于Sobel边缘检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!