CrazyBingo

【连载7.3.4.】Median_Filter均值滤波算法的实现

0
阅读(3812)

这一节忘了,今天补上!


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

3.jpg

    从图中可知,首先对,每行的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个像素,输出目标中值像素:

4.jpg

    最后在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):

5.jpg

    在前面已经搞定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上位机上观察处理后的视频,如下所示:

6.jpg

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

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

7.jpg

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

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

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

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