FPGA 图像处理中值滤波Verilog代码

灰度图数据>中值滤波模块

1 顶层代码:

`timescale 1ns / 1ps
//中值滤波



module image_median_filter (
    input clk,
    input reset,

    input [10:0] img_width,
    input [ 9:0] img_height,

    input        cam_vsync,  // 输入场同步信号
    input        valid_i,    // 输入数据有效信号
    input [15:0] rgb_565_i,  // 输入的16位RGB图像数据


    output        cmos_frame_vsync,  //输出帧有效信号    
    output        valid_o,           // 输出数据有效信号
    output [15:0] rgb_565_o          // 输出的16位灰度图像数据
);

  //常量声明
  localparam N = 3;

  //变量声明

  reg  [23:0] img_data_o;
  wire [23:0] img_data_i;
  assign img_data_i = {rgb_565_i[15:11], 3'b000, rgb_565_i[10:5], 2'b00, rgb_565_i[4:0], 3'b000};




  wire valid_gray;
  wire [7:0] img_data_gray;

  (* mark_debug="true" *) wire valid;
  wire vsync;
  (* mark_debug="true" *) wire [7:0] prev_line_data;
  (* mark_debug="true" *) wire [7:0] cur_line_data;
  (* mark_debug="true" *) wire [7:0] next_line_data;
  reg valid_d1;
  reg vsync_d1;
  reg [7:0] prev_line_data_d1;
  reg [7:0] cur_line_data_d1;
  reg [7:0] next_line_data_d1;

  reg [7:0] prev_line_data_d2;
  reg [7:0] cur_line_data_d2;
  reg [7:0] next_line_data_d2;
  reg [10:0] x_cnt;

  reg valid_s;
  reg vsync_s;
  reg [7:0] prev_line_data_d2_s;
  reg [7:0] cur_line_data_d2_s;
  reg [7:0] next_line_data_d2_s;
  reg [7:0] prev_line_data_d1_s;
  reg [7:0] cur_line_data_d1_s;
  reg [7:0] next_line_data_d1_s;
  reg [7:0] prev_line_data_s;
  reg [7:0] cur_line_data_s;
  reg [7:0] next_line_data_s;

  wire valid_sort0;
  reg vsync_sort0;
  wire [7:0] prev_line_max_data;
  wire [7:0] prev_line_mid_data;
  wire [7:0] prev_line_min_data;

  wire [7:0] cur_line_max_data;
  wire [7:0] cur_line_mid_data;
  wire [7:0] cur_line_min_data;

  wire [7:0] next_line_max_data;
  wire [7:0] next_line_mid_data;
  wire [7:0] next_line_min_data;

  wire valid_sort1;
  reg vsync_sort1;
  wire [7:0] max_mid_data;
  wire [7:0] mid_mid_data;
  wire [7:0] min_mid_data;

  wire valid_sort2;
  reg vsync_sort2;
  wire [7:0] mid_data;

  reg valid_sort3;
  reg cmos_frame_sort3;

  image_line_buffer u_image_line_buffer (
      .clk             (clk),
      .reset           (reset),
      .img_width       (img_width),
      .img_height      (img_height),
      .valid_i         (valid_i),
      .img_data_i      (img_data_i),
      .valid_o         (valid),
      .cam_vsync_o     (vsync),
      .prev_line_data_o(prev_line_data),
      .cur_line_data_o (cur_line_data),
      .next_line_data_o(next_line_data)
  );

  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      valid_d1 <= 0;
      vsync_d1 <= 0;
      prev_line_data_d1 <= 0;
      cur_line_data_d1 <= 0;
      next_line_data_d1 <= 0;
      prev_line_data_d2 <= 0;
      cur_line_data_d2 <= 0;
      next_line_data_d2 <= 0;
    end else begin
      valid_d1 <= valid;
      vsync_d1 <= vsync;
      prev_line_data_d1 <= prev_line_data;
      cur_line_data_d1 <= cur_line_data;
      next_line_data_d1 <= next_line_data;
      prev_line_data_d2 <= prev_line_data_d1;
      cur_line_data_d2 <= cur_line_data_d1;
      next_line_data_d2 <= next_line_data_d1;
    end
  end

  //边界数据处理
  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      x_cnt <= 0;
    end else begin
      x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
    end
  end

  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      valid_s <= 0;
      vsync_s <= 0;
      prev_line_data_d2_s <= 0;
      cur_line_data_d2_s <= 0;
      next_line_data_d2_s <= 0;
      prev_line_data_d1_s <= 0;
      cur_line_data_d1_s <= 0;
      next_line_data_d1_s <= 0;
      prev_line_data_s <= 0;
      cur_line_data_s <= 0;
      next_line_data_s <= 0;
    end else begin
      valid_s <= valid_d1;
      vsync_s <= vsync_d1;
      prev_line_data_d1_s <= prev_line_data_d1;
      cur_line_data_d1_s <= cur_line_data_d1;
      next_line_data_d1_s <= next_line_data_d1;
      if (x_cnt == 0) begin
        prev_line_data_d2_s <= prev_line_data_d1;
        cur_line_data_d2_s <= cur_line_data_d1;
        next_line_data_d2_s <= next_line_data_d1;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end else if (x_cnt == img_width - 1) begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data_d1;
        cur_line_data_s <= cur_line_data_d1;
        next_line_data_s <= next_line_data_d1;
      end else begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
    end
  end

  //第1个周期
  sort u_sort0 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_s),
      .data0   (prev_line_data_d2_s),
      .data1   (prev_line_data_d1_s),
      .data2   (prev_line_data_s),
      .valid_o (valid_sort0),
      .max_data(prev_line_max_data),
      .mid_data(prev_line_mid_data),
      .min_data(prev_line_min_data)
  );

  sort u_sort1 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_s),
      .data0   (cur_line_data_d2_s),
      .data1   (cur_line_data_d1_s),
      .data2   (cur_line_data_s),
      .valid_o (),
      .max_data(cur_line_max_data),
      .mid_data(cur_line_mid_data),
      .min_data(cur_line_min_data)
  );

  sort u_sort2 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_s),
      .data0   (next_line_data_d2_s),
      .data1   (next_line_data_d1_s),
      .data2   (next_line_data_s),
      .valid_o (),
      .max_data(next_line_max_data),
      .mid_data(next_line_mid_data),
      .min_data(next_line_min_data)
  );

  //第2个周期
  sort u_sort3 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_sort0),
      .data0   (prev_line_max_data),
      .data1   (cur_line_max_data),
      .data2   (next_line_max_data),
      .valid_o (valid_sort1),
      .max_data(),
      .mid_data(max_mid_data),
      .min_data()
  );

  sort u_sort4 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_sort0),
      .data0   (prev_line_mid_data),
      .data1   (cur_line_mid_data),
      .data2   (next_line_mid_data),
      .valid_o (),
      .max_data(),
      .mid_data(mid_mid_data),
      .min_data()
  );

  sort u_sort5 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_sort0),
      .data0   (prev_line_min_data),
      .data1   (cur_line_min_data),
      .data2   (next_line_min_data),
      .valid_o (),
      .max_data(),
      .mid_data(min_mid_data),
      .min_data()
  );

  //第3个周期
  sort u_sort6 (
      .clk     (clk),
      .reset   (reset),
      .valid_i (valid_sort1),
      .data0   (max_mid_data),
      .data1   (mid_mid_data),
      .data2   (min_mid_data),
      .valid_o (valid_sort2),
      .max_data(),
      .mid_data(mid_data),
      .min_data()
  );


  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      vsync_sort0 <= 0;
      vsync_sort1 <= 0;
      vsync_sort2 <= 0;
    end else begin
      vsync_sort0 <= vsync_s;
      vsync_sort1 <= vsync_sort0;
      vsync_sort2 <= vsync_sort1;
    end
  end



  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      valid_sort3 <= 0;
      img_data_o <= 0;
      cmos_frame_sort3 <= 0;
    end else begin
      valid_sort3 <= valid_sort2;
      cmos_frame_sort3 <= vsync_sort2;
      //灰度图像
      img_data_o <= {3{mid_data}};
    end
  end
  assign valid_o = valid_sort3;
  assign cmos_frame_vsync = cmos_frame_sort3;
  assign rgb_565_o = {{img_data_o[23:19], img_data_o[15:10], img_data_o[7:3]}};

endmodule

2 三行缓存代码:

`timescale 1ns / 1ps
//3行缓存



module image_line_buffer (
    input wire clk,
    input wire reset,

    input wire [10:0] img_width,
    input wire [ 9:0] img_height,

    input wire valid_i,
    input wire [23:0] img_data_i,

    output reg valid_o,
    output reg cam_vsync_o,
    output reg [23:0] prev_line_data_o,
    output reg [23:0] cur_line_data_o,
    output reg [23:0] next_line_data_o
);

  //常量声明
  parameter N = 3;  //窗口大小

  //变量声明
  genvar i;
  integer j;
  wire [0:0] valid[0:N-1];
  wire [23:0] data[0:N-1];

  reg [10:0] out_data_cnt;
  reg [9:0] out_line_cnt;
  reg ch_valid;
  reg ch_cam_vsync;
  reg [23:0] ch_data[0:N-1];

  assign valid[0] = valid_i;
  assign data[0]  = img_data_i;

  //行缓存模块, 只需要缓存N-1个fifo即可
  generate
    for (i = 1; i < N; i = i + 1) begin : lb

      line_buffer u_line_buffer (
          .clk      (clk),
          .reset    (reset),
          .img_width(img_width),
          .valid_i  (valid[i-1]),
          .data_i   (data[i-1]),
          .valid_o  (valid[i]),
          .data_o   (data[i])
      );
    end
  endgenerate

  //按照上一行、当前行、下一行输出
  //特殊情况,可根据需求设定,是复制还是给0
  //第1个行缓存,是整个画面的第1行时, 上一行数据不存在,复制第1个行缓存或者直接为0输出
  //第1个行缓存,是整个画面的最后1行时,下一行数据不存在,复制第1个行缓存输出
  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      for (j = 0; j < 3; j = j + 1) ch_data[j] <= 0;
    end else if (valid[N-2]) begin
      ch_data[1] <= data[1];
      if (out_line_cnt == 0) begin
        ch_data[2] <= data[0];
        ch_data[0] <= data[0];
      end else if (out_line_cnt == img_height - 1) begin
        ch_data[2] <= data[2];
        ch_data[0] <= data[2];
      end else begin
        ch_data[2] <= data[2];
        ch_data[0] <= data[0];
      end
    end
  end


  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      ch_valid <= 0;
      out_data_cnt <= 0;
      out_line_cnt <= 0;
    end else begin
      ch_valid <= valid[N-2];
      out_data_cnt <= valid[N-2] ? ((out_data_cnt == img_width - 1) ? 0 : out_data_cnt + 1) : out_data_cnt;
      ch_cam_vsync <= (out_line_cnt == img_height - 1) ? 1 : 0;
      out_line_cnt <= valid[N-2]&&(out_data_cnt == img_width - 1) ? ((out_line_cnt == img_height - 1) ? 0 : out_line_cnt + 1) : out_line_cnt;
    end
  end

  //单路输出
  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      valid_o <= 0;
      prev_line_data_o <= 0;
      cur_line_data_o <= 0;
      next_line_data_o <= 0;
    end else begin
      valid_o <= ch_valid;
      prev_line_data_o <= ch_data[2];
      cur_line_data_o <= ch_data[1];
      next_line_data_o <= ch_data[0];
      cam_vsync_o <= ch_cam_vsync;
    end
  end


endmodule

3 一行缓存代码:

`timescale 1ns / 1ps
//1行缓存



module line_buffer (
    input wire clk,
    input wire reset,

    input wire [10:0] img_width,

    input wire valid_i,
    input wire [23:0] data_i,

    output wire valid_o,
    output wire [23:0] data_o
);

  //变量声明

  wire rd_en;
  wire [10:0] fifo_data_count_w;

  assign rd_en   = valid_i && (fifo_data_count_w == img_width) ? 1'b1 : 1'b0;
  assign valid_o = rd_en;

  fifo_line_buffer u_fifo_line_buffer (
      .clk  (clk),      // input wire clk
      .srst (!reset),   // input wire srst
      .din  (data_i),   // input wire [23 : 0] din
      .wr_en(valid_i),  // input wire wr_en
      .rd_en(rd_en),    // input wire rd_en
      .dout (data_o),   // output wire [23 : 0] dout

      .data_count(fifo_data_count_w)  // output wire [10 : 0] data_count
  );


endmodule

 

 

4 排序代码:

`timescale 1ns / 1ps
//中值滤波排序模块
//接收三个8位的数据输入(data0, data1, data2),以及它们各自的标识符(data0_id, data1_id, data2_id),然后输出排序后的最大值、中值和最小值以及它们对应的标识符


module sort (
    input clk,
    input reset,

    input valid_i,
    input [7:0] data0,
    input [7:0] data1,
    input [7:0] data2,
    input [3:0] data0_id,
    input [3:0] data1_id,
    input [3:0] data2_id,

    output reg valid_o,
    output reg [7:0] max_data,
    output reg [7:0] mid_data,
    output reg [7:0] min_data,
    output reg [3:0] max_id,
    output reg [3:0] mid_id,
    output reg [3:0] min_id
);

  always @(posedge clk or negedge reset) begin
    if (!reset) begin
      valid_o  <= 0;
      max_data <= 0;
      mid_data <= 0;
      min_data <= 0;
      max_id   <= 0;
      mid_id   <= 0;
      min_id   <= 0;
    end else begin
      valid_o <= valid_i;
      if (data0 >= data1 && data0 >= data2) begin
        max_data <= data0;
        max_id   <= data0_id;
      end else if (data1 >= data0 && data1 >= data2) begin
        max_data <= data1;
        max_id   <= data1_id;
      end else begin
        max_data <= data2;
        max_id   <= data2_id;
      end

      if ((data1 >= data0 && data0 >= data2) || (data2 >= data0 && data0 >= data1)) begin
        mid_data <= data0;
        mid_id   <= data0_id;
      end else if ((data0 >= data1 && data1 >= data2) || (data2 >= data1 && data1 >= data0)) begin
        mid_data <= data1;
        mid_id   <= data1_id;
      end else /*if((data0 >= data2 && data2 >= data1) || (data1 >= data2 && data2 >= data0))*/ begin
        mid_data <= data2;
        mid_id   <= data2_id;
      end

      if (data2 >= data0 && data1 >= data0) begin
        min_data <= data0;
        min_id   <= data0_id;
      end else if (data2 >= data1 && data0 >= data1) begin
        min_data <= data1;
        min_id   <= data1_id;
      end else  /*if(data0 >= data2 && data1 >= data2)*/ begin
        min_data <= data2;
        min_id   <= data2_id;
      end
    end
  end


endmodule

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个示例的 Verilog 代码实现自适应滤波算法的简单版本: ```verilog module AdaptiveMedianFilter ( input wire clk, // 时钟信号 input wire reset, // 复位信号 input wire [7:0] in_pixel, // 输入像素 output reg [7:0] out_pixel // 输出像素 ); reg [7:0] window [0:4][0:4]; // 窗口数组 reg [2:0] window_size; // 窗口大小 reg [7:0] min_val, max_val; // 最小和最大 reg [7:0] median_val; // // 初始化变量 initial begin window_size = 3; // 初始窗口大小为3x3 min_val = 255; // 初始化最小为最大可能 max_val = 0; // 初始化最大为最小可能 median_val = in_pixel; out_pixel = in_pixel; end // 滤波逻辑 always @(posedge clk or posedge reset) begin if (reset) begin window_size <= 3; min_val <= 255; max_val <= 0; median_val <= in_pixel; out_pixel <= in_pixel; end else begin // 更新窗口和计算最小和最大 if (window_size < 5) begin for (i = window_size-1; i >= 0; i=i-1) begin for (j = window_size-1; j >= 0; j=j-1) begin if (i == 0 && j == 0) begin window[i][j] <= in_pixel; end else begin window[i][j] <= window[i-1][j]; end min_val <= (window[i][j] < min_val) ? window[i][j] : min_val; max_val <= (window[i][j] > max_val) ? window[i][j] : max_val; end end window_size <= window_size + 1; end // 计算并更新输出像素 if (in_pixel < min_val || in_pixel > max_val) begin median_val <= (max_val + min_val) / 2; end else begin median_val <= in_pixel; end out_pixel <= median_val; end end endmodule ``` 这个示例代码实现了一个简单的自适应滤波器,其输入像素 `in_pixel` 在时钟上升沿处理,并在输出像素 `out_pixel` 上更新。窗口大小从 3x3 开始,每个时钟周期增加一个像素,直到窗口大小为 5x5。在更新窗口的同时,计算最小和最大,并根据输入像素的确定。如果输入像素的小于最小或大于最大,则将设置为最小和最大的平均;否则,将设置为输入像素的。最后,输出像素 `out_pixel` 被更新为。 请注意,这只是一个简化的示例代码,实际可能需要根据具体的需求和系统设计做出相应的修改和优化。此外,还需要适当地连接时钟信号、复位信号和数据输入输出信号,并在测试环境进行验证。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值