FPGA图像处理-中值滤波

简介

上一篇博客介绍了如何实现3x3均值滤波,本次就来实现3x3中值滤波。
中值滤波常用于去除图像的噪声,对椒盐噪声比较有效。
在每个3x3窗口中通过排序获取中间值作为输出即可。
在FPGA中以流水线方式获取3x3窗口的中值:
FPGA图像处理-中值滤波_第1张图片
图中详细描述了取得中值的步骤,同时也描述了每一级流水线需要完成的任务:

  1. 对3x3窗口的每一行进行排序
  2. 对3个max排序,取最小,对3个mid排序,取mid,对3个min排序,取max
  3. 对第二步产生的三个数进行排序,得到中值

模块简介

为了简单起见,输入输出都是valid+data形式:

module mid_filter(
    input clk,
    input rst_n,
    
    input iValid,
    input [7:0] iData,

    output oValid,
    output [7:0] oData
);

中值滤波算法的实现

获取3x3卷积模板

之前有介绍如何获取3x3卷积模板,感兴趣的可以看看
需要注意获取3x3卷积模板消耗了2时钟周期。

filter_3x3 inst_filter_3x3(
    .clk      (clk),
    .rst_n    (rst_n),
    .iValid   (iValid),
    .iData    (iData),
    .oValid   (filter_oValid),
    .oData_11 (filter_11), .oData_12 (filter_12), .oData_13 (filter_13),
    .oData_21 (filter_21), .oData_22 (filter_22), .oData_23 (filter_23),
    .oData_31 (filter_31), .oData_32 (filter_32), .oData_33 (filter_33)
);

排序模块

分析上述步骤,每一步都是对3个数进行排序,所以需要一个模块来完成这个任务,该模块消耗1时钟周期。

module sort_3(
    input clk,
    input rst_n,
    input [7:0] data1, data2, data3,
    output reg [7:0] max, mid, min
);
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n) begin
            max <= 0;
            mid <= 0;
            min <= 0;
        end else begin
            // max
            if(data1 >= data2 && data1 >= data3)
                max <= data1;
            else if(data2 >= data1 && data2 >= data3)
                max <= data2;
            else
                max <= data3;

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

            // min
            if(data1 <= data2 && data1 <= data3)
                min <= data1;
            else if(data2 <= data1 && data2 <= data3)
                min <= data2;
            else
                min <= data3;
        end
    end
endmodule

第一级流水线

对3x3窗口的每一行进行排序

// sort of 3x3 line1
sort_3 inst_sort_3_11(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (filter_11),
    .data2 (filter_12),
    .data3 (filter_13),
    .max   (max1),
    .mid   (mid1),
    .min   (min1)
);

// sort of 3x3 line2
sort_3 inst_sort_3_12(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (filter_21),
    .data2 (filter_22),
    .data3 (filter_23),
    .max   (max2),
    .mid   (mid2),
    .min   (min2)
);

// sort of 3x3 line3
sort_3 inst_sort_3_13(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (filter_31),
    .data2 (filter_32),
    .data3 (filter_33),
    .max   (max3),
    .mid   (mid3),
    .min   (min3)
);

第二级流水线

对3个max排序,取最小,对3个mid排序,取mid,对3个min排序,取max

// min of max1 max2 max3
sort_3 inst_sort_3_21(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (max1),
    .data2 (max2),
    .data3 (max3),
    .max   (),
    .mid   (),
    .min   (min_of_max)
);

// mid of mid1 mid2 mid3
sort_3 inst_sort_3_22(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (mid1),
    .data2 (mid2),
    .data3 (mid3),
    .max   (),
    .mid   (mid_of_mid),
    .min   ()
);

// max of min1 min2 min3
sort_3 inst_sort_3_23(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (min1),
    .data2 (min2),
    .data3 (min3),
    .max   (max_of_min),
    .mid   (),
    .min   ()
);

第三级流水线

对第二级产生的三个数进行排序,得到中值

sort_3 inst_sort_3_3(
    .clk   (clk),
    .rst_n (rst_n),
    .data1 (min_of_max),
    .data2 (mid_of_mid),
    .data3 (max_of_min),
    .max   (),
    .mid   (mid_of_nine),
    .min   ()
);

获取3x3卷积模板消耗了2时钟周期,中值滤波消耗了3时钟周期,所以输出值延后输入值5个时钟周期,oValid信号也要进行延迟,比iValid慢5个时钟周期。

testbench

和之前类似,仿真3行像素,每行640个像素点。

`timescale 1ps/1ps
module mid_filter_tb;
    reg clk = 1'b1;
    always #10 clk = ~clk;
    reg rst_n = 1'b0;

    reg iValid = 1'b0;
    reg [7:0] iData = 0;

    wire oValid;
    wire [7:0] oData;

    initial begin
        #20 rst_n <= 1'b1;
        #20 iValid <= 1'b1;

        // 第一行数据
        repeat(640) begin
            iData <= $random;
            #20;
        end
        iValid <= 1'b0;

		// 第二行数据
        #100 iValid <= 1'b1;
        repeat(640) begin
            iData <= $random;
            #20;
        end
        iValid <= 1'b0;

		// 第三行数据
        #100 iValid <= 1'b1;
        repeat(640) begin
            iData <= $random;
            #20;
        end
        #500 $stop;
    end

    mid_filter inst_mid_filter(
        .clk    (clk),
        .rst_n  (rst_n),
        .iValid (iValid),
        .iData  (iData),
        .oValid (oValid),
        .oData  (oData)
    );
endmodule

波形分析

第一行前几个像素为36,129,9,99,13
FPGA图像处理-中值滤波_第2张图片
第二行前几个像素为235,248,242,137,111
FPGA图像处理-中值滤波_第3张图片
第三行前几个像素为121,205,146,69,169
FPGA图像处理-中值滤波_第4张图片
当146出现2个时钟周期后,窗口更新为36,129,9,235,248,242,121,205,146,再经过3个时钟周期的中值滤波流水线操作,输出为146,手算结果也为146,验证正确。
当69出现2个时钟周期后,窗口更新为129,9,99,248,242,137,205,146,69,再经过3个时钟周期的中值滤波流水线操作,输出为137,手算结果也为137,验证正确。

你可能感兴趣的:(Quartus,FPGA,Modelsim,fpga开发,图像处理,人工智能)