PotatoPie 4.0 实验教程(28) —— FPGA实现sobel算子对摄像头图像进行边缘提取

时间:2024-05-02 07:09:57

什么是sobel算子?

Sobel 算子是一种常用的边缘检测算子,用于在图像中检测边缘。它基于对图像进行梯度运算,可以帮助识别图像中灰度值变化较大的区域,从而找到图像中的边缘。

Sobel 算子通过计算图像的水平和垂直方向的一阶导数来识别边缘。具体来说,Sobel 算子使用了一个 3×3 的卷积核,分别对图像进行水平和垂直方向上的卷积运算,得到两个梯度图像,即水平梯度图像和垂直梯度图像。然后,将这两个梯度图像合并成一个梯度幅值图像,其中每个像素的幅值表示该点的梯度大小。

Sobel 算子的优点包括简单易实现、计算速度快、对噪声具有一定的抗干扰能力等。因此,它被广泛应用于图像处理中的边缘检测任务,例如目标检测、图像分割、特征提取等。

sobel算子边缘提取的步骤

Sobel 算子边缘提取的步骤如下:

  1. 灰度化: 首先将彩色图像转换为灰度图像。这是因为 Sobel 算子通常应用于灰度图像,因为它更容易处理且计算速度更快。

  2. 计算水平和垂直方向的梯度: 对灰度图像分别应用水平和垂直方向的 Sobel 算子。Sobel 算子使用一个 3×3 的卷积核对图像进行卷积操作,分别得到水平方向上的梯度图像和垂直方向上的梯度图像。

  3. 合并梯度图像: 将水平和垂直方向上的梯度图像合并成一个梯度幅值图像。合并的方法通常是计算每个像素点的梯度幅值,即水平和垂直方向上的梯度的平方和的平方根。

  4. 阈值处理: 对梯度幅值图像进行阈值处理,将梯度幅值大于某个阈值的像素点视为边缘像素,其余像素视为非边缘像素。这一步可以帮助去除噪声并将边缘区域分割出来。

  5. 边缘检测结果: 最终得到的图像即为 Sobel 算子边缘提取的结果,其中白色像素表示边缘像素,黑色像素表示非边缘像素。

总的来说,Sobel 算子边缘提取的步骤包括灰度化、计算梯度、合并梯度图像和阈值处理。这些步骤可以帮助识别图像中的边缘,并将其提取出来。

Sobel 算子

常用的 Sobel 算子是一个 3×3 的卷积核,分别包含水平方向和垂直方向上的两个卷积核。这两个卷积核分别对图像进行水平方向和垂直方向上的卷积运算,从而得到图像的梯度信息。

具体来说,常用的 Sobel 算子如下:

水平方向上的 Sobel 算子:

-1 0 1
-2 0 2
-1 0 1

垂直方向上的 Sobel 算子:

-1  -2   -1
0   0    0
1   2    1

这两个卷积核分别对图像进行水平方向和垂直方向上的卷积运算,得到水平方向和垂直方向上的梯度图像。然后,通过将这两个梯度图像合并,可以得到图像的梯度幅值图像,其中每个像素的幅值表示该点的梯度大小。

python实现运用sobel算子进行边缘提取的源码

PotatoPie 4.0 实验教程(28) —— FPGA实现sobel算子对摄像头图像进行边缘提取-Anlogic-安路论坛-FPGA CPLD-ChipDebug

MATLAB实现运用sobel算子进行边缘提取的源码

PotatoPie 4.0 实验教程(28) —— FPGA实现sobel算子对摄像头图像进行边缘提取-Anlogic-安路论坛-FPGA CPLD-ChipDebug

这段代码实现了读取彩色原图,转换为灰度图,并使用Sobel算子进行边缘检测。最后,它显示了原始彩色图像、原始灰度图像和Sobel边缘检测结果图像。流程如下:

  1. 从指定路径读取名为 “Lena.jpg” 的彩色图像。
  2. 将彩色图像转换为灰度图像。
  3. 使用Sobel算子进行边缘检测,得到边缘强度图像。
  4. 对于每个像素,根据其在Sobel边缘强度图像中的值,确定其是否为边缘。
  5. 将确定为边缘的像素值设置为1,其余像素值设置为0,得到二值化的边缘检测结果图像。
  6. 显示原始彩色图像、原始灰度图像和Sobel边缘检测结果图像,以便进行比较和分析。

效果图

FPGA工程分析

FPGA工程层次图

demo18相比,只是多了一个img_sobel_fltr的模块,也就是下面这一段代码,在从SDRAM读出来之后,经它处理后再输出hdmi_tx模块。

img_sobel_fltr u_sobel

(

.i_clk(clk_pixel),

.i_rst_n(sys_rst_n),

.i_hs(VGA_HS),

.i_vs(VGA_VS),

.i_de(VGA_DE),

.i_r(VGA_RGB[23:16]),

.i_g(VGA_RGB[15:8] ),

.i_b(VGA_RGB[7:0] ),

.threshold(8'd148),

.o_hs(slobe_hs),

.o_vs(slobe_vs),

.o_de(slobe_de),

.o_r(slobe_data[23:16]),

.o_g(slobe_data[15:8] ),

.o_b(slobe_data[7:0] )

);

img_sobel_fltr模块代码分析

首先例化一个图像缓冲模块,用于将图像从一个时钟一个像素转为一次输出三行三列9个像素。

代码为了简化示例,仅对RGB像素的G通道进行了sobel处理,实际上是需要先对图像滤波(比如高斯滤波滤除白噪声),然后进行灰度化处理,再然后再进行sobel运算,最后依据阈值进行二值化处理。

// 实例化图像缓存模块

img_buf u_img_buf (

.i_clk(i_clk),

.i_rst_n(i_rst_n),

.i_de(i_de),

.i_data(i_g),

.o_de(),

.o_p11(g_p11),

.o_p12(g_p12),

.o_p13(g_p13),

.o_p21(g_p21),

.o_p22(g_p22),

.o_p23(g_p23),

.o_p31(g_p31),

.o_p32(g_p32),

.o_p33(g_p33)

);

然后对每9个像进行一次soble运算,分别进行X方向和Y方向的计算,在代码中有详细注释讲解sobel运算在FPGA中的实现和优化方法。

最后对代码进行阈值比较,输出二值图

管脚约束

PotatoPie 4.0 实验教程(18) —— FPGA实现OV5640摄像头采集以SDRAM作为显存进行HDMI输出显示相同,不作赘述。

时序约束

PotatoPie 4.0 实验教程(18) —— FPGA实现OV5640摄像头采集以SDRAM作为显存进行HDMI输出显示相同,不作赘述。

实验结果图

原图

阈值为189时的边缘提取图

有部分细节丟失了,可以调节阈值参数来恢复。

阈值为149时的边缘提取图