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

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

手机扫码

20240416075513933-1713225291635

链接直达

https://item.taobao.com/item.htm?ft=t&id=776516984361

什么是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算子进行边缘提取的源码

这段Python代码实现了以下功能:

  1. 导入必要的库:os 用于操作文件路径,cv2 用于图像处理,numpy 用于数值计算,matplotlib.pyplot 用于图像显示。
  2. 获取当前脚本所在目录,并构建图像文件的完整路径。
  3. 使用 OpenCV 的 imread 函数读取彩色原图,并使用 cvtColor 函数将其转换为灰度图像。
  4. 获取灰度图像的尺寸,并将其转换为双精度类型,并进行归一化处理(除以 255)。
  5. 初始化用于存储 Sobel 边缘检测结果的图像,大小与灰度图像相同。
  6. 遍历灰度图像的每个像素点,分别计算 Sobel 算子在 x 方向和 y 方向上的梯度。
  7. 根据 Sobel 边缘强度的阈值(95/255)将像素点二值化为黑白。
  8. 使用 Matplotlib 的 imshow 函数显示原始彩色图像、原始灰度图像和 Sobel 边缘检测结果图像。

这段代码通过 Sobel 算子实现了边缘检测,展示了原始彩色图像、原始灰度图像和 Sobel 边缘检测结果图像。

20240418163608204-image

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

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

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

效果图
20240418162836117-image

FPGA工程分析

FPGA工程层次图

20240418181120830-image

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输出显示相同,不作赘述。

实验结果图

原图

20240418164602552-image

阈值为189时的边缘提取图

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

20240418164613511-image

阈值为149时的边缘提取图

20240418174919616-1713433724409

请登录后发表评论

    没有回复内容