【博文连载】Median_Filter均值滤波算法的实现

ChinaAET《电子应用技术》出版过一篇值得参考的《基于FPGA的实时中值滤波器的硬件实现》,该文采用FPGA+SRAM实现了实时中值滤波,思维值得参考(当然Bingo认为实时实现仅用Shift_RAM就够用)。Okay,转移话题,我们现在的重点是如何快速求得9个值的均值,该论文介绍了某种快速排序法,如下图所示:

从图中可知,首先对,每行的3个像素进行排序,接着提取三个最大值中的最小值,最小值中的最大值,以及中值中的中值;最后再在得到的三个值中,提取中间值,得到最后的结果。整个计算耗费了3个clk,而不需要冒泡法去实现,时间上非常的节省。

在前面经过VIP_Matrix_Generate_3X3_8Bit模块的设计,花了九牛二虎之力,我们终于得到了梦想中的3*3像素阵列,每个像素为8Bit深度。此时开始设计实现均值滤波算法。

(1)首先分别对每行3个像素进行排序,Verilog HDL的实现,由于并行特性,我们只需要一个时钟,实现如下:

module    Sort3

(

input               clk,

input               rst_n,

input       [7:0]   data1, data2, data3,

output  reg [7:0]   max_data, mid_data, min_data

);

//-----------------------------------

//Sort of 3 datas

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

max_data <= 0;

mid_data <= 0;

min_data <= 0;

end

else

begin

//get the max value

if(data1 >= data2 && data1 >= data3)

max_data <= data1;

else if(data2 >= data1 && data2 >= data3)

max_data <= data2;

else//(data3 >= data1 && data3 >= data2)

max_data <= data3;

//get the mid value

if((data1 >= data2 && data1 <= data3) || (data1 >= data3 && data1 <= data2))

mid_data <= data1;

else if((data2 >= data1 && data2 <= data3) || (data2 >= data3 && data2 <= data1))

mid_data <= data2;

else//((data3 >= data1 && data3 <= data2) || (data3 >= data2 && data3 <= data1))

mid_data <= data3;

//ge the min value

if(data1 <= data2 && data1 <= data3)

min_data <= data1;

else if(data2 <= data1 && data2 <= data3)

min_data <= data2;

else//(data3 <= data1 && data3 <= data2)

min_data <= data3;

end

end

上述电路实现了第一步的运算,新建Median_Filter_3X3.v,例化Sort3如下:

//Step1

wire  [7:0]   max_data1, mid_data1, min_data1;

Sort3 u_Sort3_1

(

.clk        (clk),

.rst_n      (rst_n),

.data1      (data11),

.data2      (data12),

.data3      (data13),

.max_data   (max_data1),

.mid_data   (mid_data1),

.min_data   (min_data1)

);

(2)接着,对三行像素取得的排序进行处理,即提取三个最大值中的最小值,三个最小值中的最大值,以及三个中间值的中间值。这里直接例化Sort3模块即可,如下所示:

//Step2

wire  [7:0]   max_min_data, mid_mid_data, min_max_data;

Sort3 u_Sort3_4

(

.clk        (clk),

.rst_n      (rst_n),

.data1      (max_data1),

.data2      (max_data2),

.data3      (max_data3),

.max_data   (),

.mid_data   (),

.min_data   (max_min_data)

);

Sort3 u_Sort3_5

(

.clk        (clk),

.rst_n      (rst_n),

.data1      (mid_data1),

.data2      (mid_data2),

.data3      (mid_data3),

.max_data   (),

.mid_data   (mid_mid_data),

.min_data   ()

);

Sort3 u_Sort3_6

(

.clk        (clk),

.rst_n      (rst_n),

.data1      (min_data1),

.data2      (min_data2),

.data3      (min_data3),

.max_data   (min_max_data),

.mid_data   (),

.min_data   ()

);

(3)最后,将(2)中得到的三个值,再次取中值,求得最终9个像素的中值,如下:

//step3

Sort3 u_Sort3_7

(

.clk        (clk),

.rst_n      (rst_n),

.data1      (max_min_data),

.data2      (mid_mid_data),

.data3      (min_max_data),

.max_data   (),

.mid_data   (target_data),

.min_data   ()

);

Okay,从(1)-(3),我们花费了3个clock,完成了3*3像素阵列的中值提取。这三个步骤的RTL图如下所示,输入9个像素,输出目标中值像素:

最后在VIP_Gray_Median_Filter.v中的中值提取例化如下:

//Median Filter of 3X3 datas, need 3 clock

wire  [7:0]   mid_value;

Median_Filter_3X3 u_Median_Filter_3X3

(

.clk            (clk),

.rst_n          (rst_n),

//ROW1

.data11         (matrix_p11),

.data12         (matrix_p12),

.data13         (matrix_p13),

//ROW2

.data21         (matrix_p21),

.data22         (matrix_p22),

.data23         (matrix_p23),

//ROW3

.data31         (matrix_p31),

.data32         (matrix_p32),

.data33         (matrix_p33),

.target_data    (mid_value)

);

既然耗费了3个时钟,那行场、像素使能也需要相应的移动3个时钟,来保持同步,这一点非常的重要,如下:

//------------------------------------------

//lag 3 clocks signal sync

reg   [2:0]   per_frame_vsync_r;

reg   [2:0]   per_frame_href_r;

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

per_frame_vsync_r <= 0;

per_frame_href_r <= 0;

end

else

begin

per_frame_vsync_r   <=  {per_frame_vsync_r[1:0],    matrix_frame_vsync};

per_frame_href_r    <=  {per_frame_href_r[1:0],     matrix_frame_href};

end

end

assign    post_frame_vsync    =   per_frame_vsync_r[2];

assign    post_frame_href     =   per_frame_href_r[2];

assign    post_img_Gray       =   post_frame_href ? mid_value : 8'd0;

最后,给出中值滤波的Modelsim仿真图,如下图所示(新架构没有*_clken):

在前面已经搞定3*3的基础上,实现个中值滤波已经非常轻松了,当然前提是您已经掌握了这些设计内容。在VIP_Image_Processor中例化VIP_Gray_Median_Filter,如下所示:

//--------------------------------------

//Gray Image median filter for better picture quality.

wire              post3_frame_vsync;  //Processed Image data vsync valid signal

wire              post3_frame_href;   //Processed Image data href vaild  signal

wire      [7:0]   post3_img_Gray;     //Processed Image Gray output

VIP_Gray_Median_Filter

#(

.IMG_HDISP  (IMG_HDISP),    //640*480

.IMG_VDISP  (IMG_VDISP)

)

u_VIP_Gray_Median_Filter

(

//global clock

.clk                    (clk),               //cmos video pixel clock

.rst_n                  (rst_n),                //global reset

//Image data prepred to be processd

.per_frame_vsync        (post2_frame_vsync),        //Prepared Image data vsync valid signal

.per_frame_href         (post2_frame_href),     //Prepared Image data href vaild  signal

.per_img_Gray           (post2_img_Gray),           //Prepared Image brightness input

//Image data has been processd

.post_frame_vsync       (post3_frame_vsync),    //Processed Image data vsync valid signal

.post_frame_href        (post3_frame_href),     //Processed Image data href vaild  signal

.post_img_Gray          (post3_img_Gray)        //Processed Image brightness output

);

`else

assign    post3_frame_vsync = post2_frame_vsync;

assign    post3_frame_href = post2_frame_href;

assign    post3_img_Gray = post2_img_Gray;

最后,全编译、生成下载jic文件,在VGA或者PC上位机上观察处理后的视频,如下所示:

上图左为原始灰度图像,上图右为中值滤波后的图像,可见中值滤波后的图像相对暗了一点,因为最大值被舍去了。但相对于均值滤波而言,中值滤波在滤除噪声的基础上,有效的保存了细节。

此外,顺便说说均值滤波和中值滤波的效果区别,这里对比一下如下图:

上图左为均值滤波图像,上图右为中值滤波后的图像。从图分析,可见均值滤波后的图像,较中值滤波处理的图像,模糊而又丧失了细节。对于椒盐噪声类的处理,中值滤波的优势要比均值滤波大。

此正如前面说的,图像处理中滤波算法有很多,但是万变不离其宗,掌握了最基本的图像处理,更多的模板算法处理方式,也就是移植与实现的问题。Bingo在此介绍了最基本的中值滤波算法的FPGA实现,更典型、富有针对性、更NB的滤波算法,有待读者自己去研究实现!

VIP图像处理,让世界变得更精彩!

郑重声明:只有100%掌握了这一章,才能了解Bingo VIP算法实现的精髓,才有继续往下看的意义!!!

 

(0)

相关推荐

  • 阻塞赋值和非阻塞赋值深度解析——仿真事件的调度

    来源:EETOP BLOG   作者:acgoal http://www.eetop.cn/blog/html/46/553746-51456.html 下面有一段verilog代码和仿真文件,用的是 ...

  • FPGA实现除法运算

    来源:weiqi7777 的 EETOP BLOG http://www.eetop.cn/blog/html/26/952026-39199.html 我们用软件编程的时候,用到除法的时候,一个/这 ...

  • 一天一个设计实例-门控时钟和使能时钟

    门控时钟的简介: 组合逻辑中多用门控时钟,一般驱动门控时钟的逻辑都是只包含一个门,如果有其他的附加逻辑,就容易因竞争而产生不希望的毛刺.门控时钟通过一个时能信号控制时钟的开关.当系统不工作时可以关闭时 ...

  • 二进制转BCD码

    应用: 用fpga实现对数码管显示,以前通常的方法是进行整除和取余进行运算,但是fpga并不擅长乘法除法运算,所以可以用BCD码来转换. BCD码:通俗的可以理解为用四位二进制数表示一位十进制数字.例 ...

  • 二进制转BCD码需要几步?

    Hi,大家好!我是至芯科技的李老师. 今天讲课的题目比较有意思,它是一个小问题:把二进制变成BCD码需要几步? 请大家思考一下.有同学可能回答需要三步,为什么啊? 因为啊,把大象放进冰箱里需要三步,第 ...

  • FPGA 的布局规划艺术

    布局规划是为设计增加布局布线约束的过程.一个大型高速设计的布局规划是实现时序收敛的关键.好的布局规划可以大大提高设计性能,并确保设计结果的质量.差的布局规划具有相反的效果,使其无法满足时序约束,并导致 ...

  • 【博文连载】【VGA+USB】灰度图像的均值滤波算法实现

    图像处理算法可以在RGB域处理,也可以在灰度域处理,牛逼的还可以在Bayer处理.但是大部分目标识别.跟踪.检测等图像处理算法,都是灰度域处理的,因为灰度除了没有色度,以及包含了基本图像处理所需的信息 ...

  • 【博文连载】中值滤波算法的介绍

    言归正传,我们先挑一个相对最简单的滤波算法(其实均值滤波更简单,但是它对边缘的保持太差,那就稍微努力点用中值滤波吧).进行中值滤波不仅可以去除孤点噪声,而且可以保持图像的边缘特性,不会使图像产生显著的 ...

  • (2条消息) opencv学习(十九)之均值滤波blur

    从本篇开始采用opencv3.2版本进行编译!!! 均值滤波是一种典型的线性滤波算法,主要是利用像素点邻域的像素值来计算像素点的值.其具体方法是首先给出一个滤波模板kernel,该模板将覆盖像素点周围 ...

  • Python | KMP算法的实现

    引言 每一本<数据结构>方面的书应该都会讲KMP算法,KMP算法可以说是知名度非常高的算法之一,为什么会叫做KMP算法?是因为KMP是由三位大牛:D.E.Knuth.J.H.Morris和 ...

  • 【从零学习OpenCV 4】均值滤波

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<从零学习OpenCV 4>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 全相位FFT算法的实现

    原文地址:全相位FFT算法的实现作者:wounder 传统FFT利用三角函数的正交性,将信号分离出来,从而将时域的信号变换到频域.但是,它有一个很重要的前提:输入的序列必须是周期内等间隔采样的值,这样 ...

  • ML之SVM:基于Js代码利用SVM算法的实现根据Kaggle数据集预测泰坦尼克号生存人员

    ML之SVM:基于Js代码利用SVM算法的实现根据Kaggle数据集预测泰坦尼克号生存人员 实验数据 设计思路 实现代码(部分代码) /** js代码实现SVM算法 */ //ML之SVM:基于Js代 ...

  • 【博文连载】动态Sobel阀值的HDL实现

    完美是没有极限的,前面我们已经实现了固定阀值下,图像的边缘检测结果.不过如何能手动输入,或者控制阀值的大小,那其实更完美一点点. 既然我们能够在努力一点点,为何要放弃??? OK,Bingo这里打算教 ...

  • 【博文连载】Sobel边缘检测算法的HDL实现

    FPGA中针对以上矩阵进行算法移植.由于直接计算会因为负值而得到错误的结果,用补码表示比较繁琐,需要用到unsigned 以及signed类型,不适合FPGA的运算. cnblog有真oo无双的代码, ...