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

一、原理

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

2.抽头原理

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

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

3.求中值算法

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

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

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

二、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,作为中值滤波的输出。

综合结果:

 

  • 13
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
自适应中值滤波是一种用于图像处理的滤波算法,它可以有效地去除图像中的噪声。在 Verilog实现自适应中值滤波可以通过以下步骤完成: 1. 定义输入和输出信号:首先,你需要定义输入图像和输出图像的信号,可以使用 Verilog 的数据类型来表示像素值和图像尺寸。 2. 读取输入图像:你可以使用适当的模块或方法来读取输入图像。这可以通过从文件中读取图像数据或者从其他模块接收输入信号来实现。 3. 实现自适应中值滤波算法:自适应中值滤波算法通常包括以下步骤: - 对于每个像素,选择一个窗口大小(如3x3或5x5)。 - 将该窗口内的像素值排序,找到中值。 - 计算该窗口内的最小值和最大值。 - 如果中值小于最小值或大于最大值,则将中值替换为该窗口内的中间值。 - 将中值作为输出图像中对应位置的像素值。 这些步骤可以使用 Verilog 的逻辑运算和比较运算符来实现。 4. 写入输出图像:最后,你需要将输出图像写入到适当的位置,可以通过文件或者输出信号的方式实现。 需要注意的是,Verilog 是一种硬件描述语言,主要用于设计和描述硬件电路。因此,在实际使用中,你可能需要将图像数据转换为适当的格式来进行处理,并将处理结果转换回图像格式。此外,自适应中值滤波算法的实现可能需要一些额外的控制逻辑和状态机来处理边界情况和处理过程中的状态转换。 希望这些信息能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bluebub

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值