[图像处理]3×3中值滤波的verilog实现

一、原理

1.将连续输入的9个灰度值存入移位寄存器,并通过抽头形成3×3矩阵,而后通过组合逻辑输出9个数的中值。

2.抽头原理

[图像处理]3×3中值滤波的verilog实现_第1张图片

 因为数据存入shift reg需要一拍的时间,若选用5、2抽头需要对input单独延迟一拍,本例选用6、3抽头以及input作为滤波矩阵的列输入,避免对input的单独延迟处理。

每个时钟上升沿到来时,矩阵左列为抽头输入,其他列依次右移,如图所示。

3.求中值算法

①将9个数分成3组,每组3个数。求每一组的最大值、中值、最小值

②对3个最大值求最小值,对3个最小值求最大值,对3个中值求中值,得到3个数

③对这三个数求中值,这个数也是9个像素的中值

[图像处理]3×3中值滤波的verilog实现_第2张图片

二、verilog实现

顶层模块:


// Module Name: mid_9_nums    
// Target Device: xc7z010clg400-1
// Tool versions: vivado 2017.4
// Last Version: 2022.4.18
// Description: mid_filter 



//port define
module mid_9_nums(
    input                clk,
    input                rst_n,
    input        [7:0]   data_in,
    output       [7:0]   data_out
);


parameter length = 9; 
reg [7:0] data_reg [length-1:0];//9 shift reg


/*********max/mid/min reg**********/
wire [7:0] data_max [2:0];
wire [7:0] data_mid [2:0];
wire [7:0] data_min [2:0];
wire [7:0] data_min_max;
wire [7:0] data_max_min;
wire [7:0] data_mid_mid;
/**********************************/


/**************matrix**************/
reg [7:0] m11,m12,m13;
reg [7:0] m21,m22,m23;
reg [7:0] m31,m32,m33;
/**********************************/

wire [7:0] row1,row2;
reg	[7:0] row3;

integer i;


//9 nums shift reg
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        for(i = 0; i < length; i = i + 1)begin
            data_reg[i] <= 8'b0;
        end
    end
    else begin
        for(i = 0; i < length - 1; i = i + 1)begin
            data_reg[i+1] <= data_reg[i];
            data_reg[0]   <= data_in;
        end
    end
end


/**************taps**************

        →-----6    . . . -------→   9 nums shift reg
        ↑
       |5  4  3|
              ↑
        →-----→
        ↑
       |2  1  0|
              ↑
            data_in

********************************/
assign row1 = data_reg[6];
assign row2 = data_reg[3];

always @(posedge clk)begin 
    row3 <= data_in;
end


//3*3 filter matrix
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        {m11,m12,m13,m21,m22,m23,m31,m32,m33} <= 72'd0;
    end
    else begin
        {m11,m12,m13} <= {m12,m13,row1};
        {m21,m22,m23} <= {m22,m23,row2};
        {m31,m32,m33} <= {m32,m33,row3};
    end
end


//output must be wire type
//input port must be connected
//instance
min_mid_max_3 stage1_tmp1(m11,m12,m13, data_min[2], data_mid[2], data_max[2]);
min_mid_max_3 stage1_tmp2(m21,m22,m23, data_min[1], data_mid[1], data_max[1]);
min_mid_max_3 stage1_tmp3(m31,m32,m33, data_min[0], data_mid[0], data_max[0]);


min_mid_max_3 stage2_tmp1(.in1(data_min[2]),.in2(data_min[1]),.in3(data_min[0]),.min(),.mid(),.max(data_min_max));
min_mid_max_3 stage2_tmp2(.in1(data_mid[2]),.in2(data_mid[1]),.in3(data_mid[0]),.min(),.mid(data_mid_mid),.max());
min_mid_max_3 stage2_tmp3(.in1(data_max[2]),.in2(data_max[1]),.in3(data_max[0]),.min(data_max_min),.mid(),.max());

min_mid_max_3 stage3_tmp(.in1(data_min_max),.in2(data_mid_mid),.in3(data_max_min),.min(),.mid(data_out),.max());

endmodule

 子模块:求三个数的最大值、最小值、中值


// Module Name: min_mid_max_3    
// Target Device: xc7z010clg400-1
// Tool versions: vivado 2017.4
// Description: take the middle value / minimum / maximum of 3 numbers



module min_mid_max_3(
    input       [7:0] in1,
    input       [7:0] in2,
    input       [7:0] in3,
    output reg  [7:0] min,
    output reg  [7:0] mid,
    output reg  [7:0] max
);

always @(*)begin
if(in1 > in2)begin

        if(in2 > in3)begin
            max = in1;
            mid = in2;
            min = in3;
        end
        else begin
            if(in1 > in3)begin
                max = in1;
                mid = in3;
                min = in2;
            end
            else begin
                max = in3;
                mid = in1;
                min = in2;
            end
        end
    end
else begin//1<2

        if(in1 > in3)begin
            max = in2;
            mid = in1;
            min = in3;
        end

        else begin
            if(in2 > in3)begin
                max = in2;
                mid = in3;
                min = in1;
            end
            else begin
                max = in3;
                mid = in2;
                min = in1;
            end
        end
    end
end

endmodule

testbench:

`timescale 1ns / 1ps

module tb_mid_num();

//10mhz
parameter CLK_PERIOD = 100;

reg             clk;
reg             rst_n;
reg     [7:0]   data_in;
wire    [7:0]   data_out;

always # (CLK_PERIOD/2) clk = ~clk;

initial begin
    clk = 1'b0;
    rst_n = 1'b0;
    #300
    rst_n = 1'b1;
end

//random input
always @(posedge clk)begin
    data_in = {$random}%256;
end

//instance
mid_9_nums u_mid_num(clk, rst_n, data_in, data_out);

endmodule

三、仿真

从截取的部分仿真结果来看,当输入为连续的225、23、67、201、134、37、193、141、90时,下一个时钟上升沿来临时,67/37/90组成一列输入到中值滤波的3*3矩阵,并通过中值算法求出中值134,作为中值滤波的输出。

[图像处理]3×3中值滤波的verilog实现_第3张图片

综合结果:

 [图像处理]3×3中值滤波的verilog实现_第4张图片

你可能感兴趣的:(Verilog学习笔记,fpga开发)