前言
这篇文章主要讲解一下用FPGA实现图像的均值滤波算法,为什么要写这篇文章呢?
主要原因:在图像领域里会对一些视频数据要做各种算法处理,去噪算法是用到最多的算法;当然图像去噪算法有很多种,例如均值滤波、中值滤波、高斯滤波、引导滤波等。学习就从最基础的算法开始,逐步提高自己的水平。
开始我们的FPGA学习之旅吧.......
图像均值滤波算法原理
对于图像均值滤波算法,我参考了书籍《图像处理》冈萨雷斯第三版。
图像均值滤波属于线性滤波算法,在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围 8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值,如下图所示:中心点为目标像素,它的最终的值要用周边的8个像素求和后的平均值代替。 公式:
![]()

对上述图像算法的通俗理解就是用上图的模板在一幅M*N的图像按照从左到右的顺序移动,每移动一次计算出一个图像数据,直到所有图像都计算完为止;明白原理后开始进入程序设计吧!
图像均值滤波程序设计
整个系统框架设计由3部分组成:image_change模块、image_storage模块、matrix_mode模块,如下图所示。下面开始详细介绍一下每个子模块的功能吧!

- 1. image_mean_top程序接口
|
名称 |
方向 |
位宽 |
说明 |
|
piexl_clk |
Input |
1 |
工作时钟 |
|
reset |
Input |
1 |
复位信号(active high) |
|
Oimage_VS_in |
Input |
1 |
原始图像输入的场信号 |
|
Oimage_HS_in |
Input |
1 |
原始图像输入的行信号 |
|
Oimage_data_in |
Input |
WIDTH |
原始图像数据信号 |
|
Pimage_VS_out |
Output |
1 |
算法处理后的场信号 |
|
Pimage_HS_out |
Output |
1 |
算法处理后的行信号 |
|
Pimage_data_out |
Output |
WIDTH |
算法处理后的数据 |
image_change模块说明
根据图像均滤波算法的原理介绍,我们可以发现一个问题就是一张图像的外围周边的像素是无法进行算法处理,通过算法处理后的图像的分辨率降低了。如下图所以,周边为红色的像素都是无法参与算法运算的,当3*3的模板在整幅图像进行算法处理后,获得的图像的大小就变成了绿色像素的范围了。在实际的图像处理中有两种办法可以解决这个问题:
第一个办法就是根据算法的模板大小,配置相机吧原始图像分辨率变大一些,保证算法处理后的图像分辨率为最终想要的分辨率;
第二种办法就是对原始图像进行修改,人工将分辨率变大,从而保证获得的分辨率为最终想要的分辨,我们这里主要讲第二种办法。

举例:原始图像的分辨率是7*3,也就是每行7个像素,一共三行数据;采用的均值滤波模板是3*3的。为了保证图像的边缘数据能够得到处理,我们需要对每行的左右两边各添加一个虚拟的像素(数值为0),这就能保证每行数据的原始像素都能得到算法运算,同时保证了算法运算后每行的数据的个数不变;同理对行数上我们也要添加两行虚拟行数保证算法运算后的行数不边;image_change模块就是按照这个思路设计的。
备注:对行数的处理,本模块在原始图像的结尾处添加一行,对于开头的添加的虚拟行通过后面的模块来实现。

- 1. image_change程序接口
|
名称 |
方向 |
位宽 |
说明 |
|
piexl_clk |
Input |
1 |
工作时钟 |
|
reset |
Input |
1 |
复位信号(active high) |
|
Oimage_VS_in |
Input |
1 |
原始图像输入的场信号 |
|
Oimage_HS_in |
Input |
1 |
原始图像输入的行信号 |
|
Oimage_data_in |
Input |
WIDTH |
原始图像数据信号 |
|
Cimage_VS_out |
Output |
1 |
算法处理后的场信号 |
|
Cimage_HS_out |
Output |
1 |
算法处理后的行信号 |
|
Cimage_data_out |
Output |
WIDTH |
算法处理后的数据 |
测试用例:
输入一行数据,该行数据共7个有效数(1~7)运算结果:每行数据的两边各添加一个像素数值为0,一行数据就变成了9个像素,同时行数变成两行,补充的一行填充的数据全部为0。
仿真结果:
通过仿真结果证明了我们的程序设计是正确的!

image_storage模块说明
在真实的视频图像数据中,数据都是一行行的输出,为了能够实现3*3模板的运算,需要对图像数据进行缓存,从而模拟出三行并行数据。

实现这个缓存常用的方法就是调用FPGA内部的缓存资源来实现,一般大家常用的就是shift_ram、fifo、双端口ram,其中shift_ram是最常用的(因为操作简单);这次设计没有调用上面的资源,我是自己设计了一个shift_ram的IP来实现,一个原因是block_ram缓存资源在FPGA中太宝贵了,一定要省着用;另一个原因是自己设计的IP可以在不同厂家的FPGA芯片中使用,移植起来比较方便(我了解的卖IP核的都是这样搞,大家可以尝试一下)。Shift_ram的IP设计,我采用了Verilog语法中的generate语句实现的,该语句操作简便灵活,我个人认为FPGA工程师必须掌握的,大家可以学习一下。

- 1. image_storage程序接口
|
名称 |
方向 |
位宽 |
说明 |
|
piexl_clk |
Input |
1 |
工作时钟 |
|
reset |
Input |
1 |
复位信号(active high) |
|
Simage_VS_in |
Input |
1 |
原始图像输入的场信号 |
|
Simage_HS_in |
Input |
1 |
原始图像输入的行信号 |
|
Simage_data_in |
Input |
WIDTH |
原始图像数据信号 |
|
Simage_VS_out |
Output |
1 |
算法处理后的场信号 |
|
Simage_HS_out |
Output |
1 |
算法处理后的行信号 |
|
Cimage_data_outA |
Output |
WIDTH |
算法处理后的数据 |
|
Cimage_data_outB |
Output |
WIDTH |
算法处理后的数据 |
|
Cimage_data_outC |
Output |
WIDTH |
算法处理后的数据 |
仿真结果:
如下图所示,红圈内的数据是输出的第一组3*3模板数据,Cimage_data_outC输出的数据全部为零,前面说过给原图添加的第一行虚拟数据在本模块实现。通过仿真验证了本模块设计是正确的。

matrix_mode模块说明
该模块的作用就是设计一个3*3的模板,当iamge_storage模块输出9个数据时,该模块就开始计算出结果。设计思路如下图所示,就是在要设计9个缓存寄存器通过打拍实现计算功能。


- 1. Matrix_mode程序接口
|
名称 |
方向 |
位宽 |
说明 |
|
piexl_clk |
Input |
1 |
工作时钟 |
|
reset |
Input |
1 |
复位信号(active high) |
|
image_VS_in |
Input |
1 |
原始图像输入的场信号 |
|
image_HS_in |
Input |
1 |
原始图像输入的行信号 |
|
image_data_out |
Output |
WIDTH |
原始图像数据信号 |
|
image_VS_out |
Output |
1 |
算法处理后的场信号 |
|
image_HS_out |
Output |
1 |
算法处理后的行信号 |
|
image_data_A |
Input |
WIDTH |
算法处理后的数据 |
|
image_data_B |
Input |
WIDTH |
算法处理后的数据 |
|
image_data_C |
Input |
WIDTH |
算法处理后的数据 |
仿真结果:如下图所示,仿真结果和均值滤波算法原理是一致的,就是把目标周边的8个像素进行加法运算后求其平均值。

本文介绍如何使用FPGA实现图像均值滤波算法,详细讲解了算法原理和程序设计,包括image_change、image_storage及matrix_mode三个模块的功能,并提供了仿真结果以验证设计的正确性。
2162

被折叠的 条评论
为什么被折叠?



