查看: 2414|回复: 2

(七)均值滤波算法实现

[复制链接]
  • TA的每日心情
    无聊
    2021-4-7 11:23
  • 签到天数: 27 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2020-1-27 23:00:22 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 雪孩爱雪 于 2020-1-27 23:05 编辑

    背景知识
       均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括
    了其周围的临近像素(以目标像素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标
    像素本身),再用模板中的全体像素的平均值来代替原来像素值。
    均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用
    均值代替原图像中的各个像素值,即对待处理的当前像素点(xy),选择一个模板,该模
    板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x
    y),作为处理后图像在该点上的灰度 gxy),即 gxy=1/m fxym 为该模
    板中包含当前像素在内的像素总个数。
    均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也
    破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。
    FPGA 的均值滤波算法实现步骤
    360截图17590901777495.png
    如图 1 所示,中心点(xy)为均值滤波将要处理的位置,
    f(x,y)表示(x,y)点的像素值,
    g(x,y)表示(x,y)点经过均值处理后的值。
    均值滤波公式表示如下:
    g(x,y)=1/8*(f(x-1,y-1)+f(x,y-1)+f(x+1,y-1)+f(x-1,y)+f(x+1,y)+f(x-1,y+1)+f(x,y+1)+f(x+1,y+1))------------------------------(1)

    由(1)式我们看出(x,y)点的 3x3 像素点的均值等于其周围邻域的八个点的像素值之和
    除以 8

    FPGA 实现步骤:
    1>形成 3x3 矩阵像素
    2>求周围邻域八个点的像素值之和 将3x3矩阵的中心像素的周围八个点求和,我们这里还是采取流水线的设计方法,来增加吞吐量,然后再求平均值代替目标像素的值
    3>将结果右移三位(相当于除以 8)得到结果



    我们要进行均值滤波首先要生成一个3x3矩阵。算法运算窗口一般采用奇数点的邻域来计算中值,最常用的窗口有3X3和5X5模型。
    下面介绍3X3窗口的Verilog实现方法。
    (1)       通过2个或者3个RAM的存储来实现3X3像素窗口;
    (2)       通过2个或者3个FIFO的存储来实现3X3像素窗口;
    (3)       通过2行或者3行Shift_RAM的存储来实现3X3像素窗口;
      要想用实现均值滤波和中值滤波,必须要先生成3x3阵列,在Xilinx系列里,可以用调用IP核——shift_RAM,具体设置参数如图所示。
    添加IP核
    360截图18720123929789.png
    搜索IP核
    360截图167708105959103.png
    IP核设置
    360截图170010175411156.png
    hift register(RAM-based)ip 主要为了形成三行像素缓存。
    这里Xilinx的shift_ram一次只能生成一行数据,所以我采用两个IP Core和正在输入的一行来生成三行数据
    module line3(
        input clk,
        input [15:0] din,
        input hs_valid_in,
        output [15:0] dout,
        output [15:0] dout_r0,
        output [15:0] dout_r1,
        output [15:0] dout_r2
        );
    line_buff line_buff0(
      .D(din),
       .CLK(clk),
       .CE(hs_valid_in),
       .Q(dout_r0)
    );
    line_buff line_buff1(
      .D(dout_r0),
       .CLK(clk),
       .CE(hs_valid_in),
       .Q(dout_r1)
    );
    line_buff line_buff2(
        .D(dout_r1),
       .CLK(clk),
       .CE(hs_valid_in),
       .Q(dout_r2)
    );
    assign dout = dout_r2;
    endmodule
    均值滤波算法(需要将图像转为灰度,转为灰度方法见之前发的):
    `timescale 1ns/1ps
    module mean_filter_3x3(
           input             clk,
                     input             rst_n,
                     
                     input [15:0]      data_in,
                     input             data_in_en,
                     
                     output  reg [15:0]data_out,
                     output            data_out_en
                     );
                     
    wire [15:0] line0;
    wire [15:0] line1;
    wire [15:0] line2;

    reg [15:0] line0_data0;
    reg [15:0] line0_data1;
    reg [15:0] line0_data2;

    reg [15:0] line1_data0;
    reg [15:0] line1_data1;
    reg [15:0] line1_data2;

    reg [15:0] line2_data0;
    reg [15:0] line2_data1;
    reg [15:0] line2_data2;

    reg        data_out_en0;
    reg        data_out_en1;
    reg        data_out_en2;
    wire        [18:0]  result_data;

    line3 line3x3_inst(
            .clken(data_in_en),
                 .clock(clk),
                 .shiftin(data_in),
                 .shiftout(),
                 .taps0x(line0),
                 .taps1x(line1),
                 .taps2x(line2)
                      );
    //----------------------------------------------------
    // Form an image matrix of three multiplied by three
    //----------------------------------------------------


    always @(posedge clk or negedge rst_n) begin
      if(!rst_n) begin
        line0_data0 <= 16'b0;
             line0_data1 <= 16'b0;
             line0_data2 <= 16'b0;
             
             line1_data0 <= 16'b0;
             line1_data1 <= 16'b0;
             line1_data2 <= 16'b0;
             
             line2_data0 <= 16'b0;
             line2_data1 <= 16'b0;
             line2_data2 <= 16'b0;
             
             data_out_en0 <= 1'b0;
             data_out_en1 <= 1'b0;
             data_out_en2 <= 1'b0;
      end
      else if(data_in_en) begin
        line0_data0 <= line0;
             line0_data1 <= line0_data0;
             line0_data2 <= line0_data1;
             
             line1_data0 <= line1;
             line1_data1 <= line1_data0;
             line1_data2 <= line1_data1;
             
             line2_data0 <= line2;
             line2_data1 <= line2_data0;
             line2_data2 <= line2_data1;

             data_out_en0 <= data_in_en;
             data_out_en1 <= data_out_en0;
             data_out_en2 <= data_out_en1;         
      end
    end


    add_8 add_8(
              .clken(data_in_en),
              .clock(clk),
              .data0x(line0),
              .data1x(line0_data0),
              .data2x(line0_data1),
              .data3x(line1),
              .data4x(line1_data1),
              .data5x(line2),
              .data6x(line2_data0),
              .data7x(line2_data1),
              .result(result_data)
              );

    always @(posedge clk or negedge rst_n) begin
      if(!rst_n)
        data_out <= 16'b0;
      else if(data_in_en)
        data_out <= result_data[18:3];
             //data_out <= line2_data1;
      else ;
    end

    endmodule

    我们将lena的照片加入椒盐噪声,如下图:

    然后生成coe文件,导入工程,下载后便可以看到滤波效果。



    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-4-18 10:48
  • 签到天数: 117 天

    连续签到: 2 天

    [LV.6]常住居民II

    发表于 2020-3-26 23:10:51 | 显示全部楼层
    FPGA的方式,学习了
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-12-28 02:31 , Processed in 0.142966 second(s), 20 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.