中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内
的所有像素点灰度值的中值.
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波
的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让
周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,
将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维
中值滤波输出为 g(x,y) =med{f(x-k,y-l),(k,l∈W)} ,其中, f(x,y), g(x,y)分别为原始图像和处理后图像。 W 为二维模板,通常为 33, 55 区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。
中值滤波法对消除椒盐噪声非常有效,在光学测量条纹图象的相位分析处理方法中有特
殊作用, 但在条纹中心分析方法中作用不大。中值滤波在图像处理中,常用于保护边缘信息,
是经典的平滑噪声的方法。要得到模板中数据的中间值,首先要将数据按大小排序,然后根据有序的数字序列来找中问值。中值滤波排序的过程有很多成熟的算法,如冒泡排序、二分排序等,大多是基于微机平台的软件算法,而适合硬件平台的排序算法则比较少。

FPGA 中值滤波实现方法

中值滤波第一个输入为二维 中值滤波算法verilog_sed

如上所示,为一个 3x3 的图像模板,
第一步:
分别对三行像素进行排序:
由 L11,L12,L13 得到 L1max, L1mid, L1min;
由 L21,L22,L23 得到 L2max, L2mid, L2min;
3)由 L31,L32,L33 得到 L3max, L3mid, L3min。
第二步:
分别对三行像素中的 3 个最大, 3 个中间和 3 个最小分别进行排序:
由 L1max, L2max, L3max 得到 Lmax_max, Lmax_mid, Lmax_min;
2)由 L1mid, L2mid, L3mid 得到 Lmid_max, Lmid_mid, Lmid_min;
3)由 Lmin, L2min, L3min 得到 Lmin_max, Lmin_mid, Lmin_min;
第三步:对最大的最小(Lmax_min),中间的中间(Lmid_mid)以及最小的最大(Lmin_max)
进行排序(例:由 Lmax_min, Lmid_mid, Lmin_max 得到 midian)。

`timescale 1ns/1ps

module median_filter(
       input             clk,
		 input             rst_n,
		 
		 input [15:0]      data_in,
		 input             data_in_en,
		 input             hs_in,
		 input             vs_in,
		 
		 output[15:0]      data_out,
		 output            data_out_en,
		 
		 output            hs_out,
		 output            vs_out
		 );
		 
wire [15:0] line0;
wire [15:0] line1;
wire [15:0] line2;

//--------------------------------------
//pipeline control signal
//--------------------------------------
reg         hs0;
reg         hs1;
reg         hs2;

reg         vs0;
reg         vs1;
reg         vs2;

reg         de0;
reg         de1;
reg         de2;
//-------------------------------------
//pipeline data
//-------------------------------------
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;

//--------------------------------------
//define line max mid min
//--------------------------------------
reg [15:0] line0_max;
reg [15:0] line0_mid;
reg [15:0] line0_min;

reg [15:0] line1_max;
reg [15:0] line1_mid;
reg [15:0] line1_min;

reg [15:0] line2_max;
reg [15:0] line2_mid;
reg [15:0] line2_min;

//----------------------------------------------
// define //max of min //mid of mid// min of max
//----------------------------------------------

reg [15:0] max_max;
reg [15:0] max_mid;
reg [15:0] max_min;

reg [15:0] mid_max;
reg [15:0] mid_mid;
reg [15:0] mid_min;

reg [15:0] min_max;
reg [15:0] min_mid;
reg [15:0] min_min;

//---------------------------------------------
// define mid of mid
//---------------------------------------------

reg [15:0] mid;

line3x3 line3x3_inst(
        .clken(data_in_en),
	     .clock(clk),
	     .shiftin(data_in),
	     .shiftout(),
	     .taps0x(line0),
	     .taps1x(line1),
	     .taps2x(line2)
		  );

//----------------------------------------------------
//delay control signal
//----------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
    hs0 <= 1'b0;
    hs1 <= 1'b0;
    hs2 <= 1'b0;

    vs0 <= 1'b0;
    vs1 <= 1'b0;
    vs2 <= 1'b0;

    de0 <= 1'b0;
    de1 <= 1'b0;
    de2 <= 1'b0;
  end
  else if(data_in_en) begin
    hs0 <= hs_in;
    hs1 <= hs0;
    hs2 <= hs1;

    vs0 <= vs_in;
    vs1 <= vs0;
    vs2 <= vs1;

    de0 <= data_in_en;
    de1 <= de0;
    de2 <= de1;  
  end
end
//----------------------------------------------------
// 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;
  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;	 
  end
  else ;
end
//-----------------------------------------------------------------------------------
//(line0 line1 line2) of (max mid min)
//-----------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
    line0_max <= 16'd0;
    line0_mid <= 16'd0;
    line0_min <= 16'd0;
  end
  else if(data_in_en) begin
    if((line0_data0 >= line0_data1) && (line0_data0 >= line0_data2)) begin
	   line0_max <= line0_data0;
		if(line0_data1 >= line0_data2) begin
		  line0_mid <= line0_data1;
		  line0_min <= line0_data2;
		end 
		else begin
		  line0_mid <= line0_data2;
		  line0_min <= line0_data1;
		end
	 end
	 else if((line0_data1 > line0_data0) && (line0_data1 >= line0_data2)) begin
	   line0_max <= line0_data1;
		if(line0_data0 >= line0_data2) begin
		  line0_mid <= line0_data0;
		  line0_min <= line0_data2;
		end 
		else begin
		  line0_mid <= line0_data2;
		  line0_min <= line0_data0;
		end
	 end
	 else if((line0_data2 > line0_data0) && (line0_data2 > line0_data1)) begin
	   line0_max <= line0_data2;
		if(line0_data0 >= line0_data1) begin
		  line0_mid <= line0_data0;
		  line0_min <= line0_data1;
		end 
		else begin
		  line0_mid <= line0_data1;
		  line0_min <= line0_data0;
		end
	 end
  end
end

always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
	 line1_max <= 16'd0;
    line1_mid <= 16'd0;
    line1_min <= 16'd0;
  end
  else if(data_in_en) begin
    if((line1_data0 >= line1_data1) && (line1_data0 >= line1_data2)) begin
	   line1_max <= line1_data0;
		if(line1_data1 >= line1_data2) begin
		  line1_mid <= line1_data1;
		  line1_min <= line1_data2;
		end 
		else begin
		  line1_mid <= line1_data2;
		  line1_min <= line1_data1;
		end
	 end
	 else if((line1_data1 > line1_data0) && (line1_data1 >= line1_data2)) begin
	   line1_max <= line1_data1;
		if(line1_data0 >= line1_data2) begin
		  line1_mid <= line1_data0;
		  line1_min <= line1_data2;
		end 
		else begin
		  line1_mid <= line1_data2;
		  line1_min <= line1_data0;
		end	 
	 end
	 else if((line1_data2 > line1_data0) && (line1_data2 > line1_data1)) begin
	   line1_max <= line1_data2;
		if(line1_data0 >= line1_data1) begin
		  line1_mid <= line1_data0;
		  line1_min <= line1_data1;
		end 
		else begin
		  line1_mid <= line1_data1;
		  line1_min <= line1_data0;
		end	 
	 end
  end
end

always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
	 line2_max <= 16'd0;
    line2_mid <= 16'd0;
    line2_min <= 16'd0;
  end
  else if(data_in_en) begin
    if((line2_data0 >= line2_data1) && (line2_data0 >= line2_data2)) begin
	   line2_max <= line2_data0;
		if(line2_data1 > line2_data2) begin
		  line2_mid <= line2_data1;
		  line2_min <= line2_data2;
		end 
		else begin
		  line2_mid <= line2_data2;
		  line2_min <= line2_data1;
		end
	 end
	 else if((line2_data1 > line2_data0) && (line2_data1 >= line2_data2)) begin
	   line2_max <= line2_data1;
		if(line2_data0 >= line2_data2) begin
		  line2_mid <= line2_data0;
		  line2_min <= line2_data2;
		end 
		else begin
		  line2_mid <= line2_data2;
		  line2_min <= line2_data0;
		end	 
	 end
	 else if((line2_data2 > line2_data0) && (line2_data2 > line2_data1)) begin
	   line2_max <= line2_data2;
		if(line2_data0 >= line2_data1) begin
		  line2_mid <= line2_data0;
		  line2_min <= line2_data1;
		end 
		else begin
		  line2_mid <= line2_data1;
		  line2_min <= line2_data0;
		end	 
	 end
  end
end
//----------------------------------------------------------------------------------
// (max_max max_mid max_min) of ((line0 line1 line2) of max)
//----------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
	 max_max <= 16'd0;
    max_mid <= 16'd0;
    max_min <= 16'd0;
  end
  else if(data_in_en) begin
    if((line0_max >= line1_max) && (line0_max >= line2_max)) begin
	   max_max <= line0_max;
		if(line1_max >= line2_max) begin
		  max_mid <= line1_max;
		  max_min <= line2_max;
		end 
		else begin
		  max_mid <= line2_max;
		  max_min <= line1_max;
		end
	 end
	 else if((line1_max > line0_max) && (line1_max >= line2_max)) begin
	   max_max <= line1_max;
		if(line0_max >= line2_max) begin
		  max_mid <= line0_max;
		  max_min <= line2_max;
		end 
		else begin
		  max_mid <= line2_max;
		  max_min <= line0_max;
		end
	 end
	 else if((line2_max > line0_max) && (line2_max > line1_max)) begin
	   max_max <= line2_max;
		if(line0_max >= line1_max) begin
		  max_mid <= line0_max;
		  max_min <= line1_max;
		end 
		else begin
		  max_mid <= line1_max;
		  max_min <= line0_max;
		end
	 end
  end
end
//------------------------------------------------------------------------------
// (mid_max mid_mid mid_min) of ((line0 line1 line2)of mid)
//------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
	 mid_max <= 16'd0;
    mid_mid <= 16'd0;
    mid_min <= 16'd0;
  end
  else if(data_in_en) begin
    if((line0_mid >= line1_mid) && (line0_mid >= line2_mid)) begin
	   mid_max <= line0_mid;
		if(line1_mid >= line2_mid) begin
		  mid_mid <= line1_mid;
		  mid_min <= line2_mid;
		end 
		else begin
		  mid_mid <= line2_mid;
		  mid_min <= line1_mid;
		end
	 end
	 else if((line1_mid > line0_mid) && (line1_mid >= line2_mid)) begin
	   mid_mid <= line1_mid;
		if(line0_mid >= line2_mid) begin
		  mid_mid <= line0_mid;
		  mid_min <= line2_mid;
		end 
		else begin
		  mid_mid <= line2_mid;
		  mid_min <= line0_mid;
		end
	 end
	 else if((line2_mid > line0_mid) && (line2_mid > line1_mid)) begin
	   mid_max <= line2_mid;
		if(line0_mid >= line1_mid) begin
		  mid_mid <= line0_mid;
		  mid_min <= line1_mid;
		end 
		else begin
		  mid_mid <= line1_mid;
		  mid_min <= line0_mid;
		end
	 end
  end
end
//------------------------------------------------------------------------------
// (min_max min_mid min_min) of ((line0 line1 line2)of min)
//------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if(!rst_n) begin
	 min_max <= 16'd0;
    min_mid <= 16'd0;
    min_min <= 16'd0;
  end
  else if(data_in_en) begin
    if((line0_min >= line1_min) && (line0_min >= line2_min)) begin
	   min_max <= line0_min;
		if(line1_min >= line2_min) begin
		  min_mid <= line1_min;
		  min_min <= line2_min;
		end 
		else begin
		  min_mid <= line2_min;
		  min_min <= line1_min;
		end
	 end
	 else if((line1_min > line0_min) && (line1_min >= line2_min)) begin
	   min_max <= line1_min;
		if(line0_min >= line2_min) begin
		  min_mid <= line0_min;
		  min_min <= line2_min;
		end 
		else begin
		  min_mid <= line2_min;
		  min_min <= line0_min;
		end
	 end
	 else if((line2_min > line0_min) && (line2_min > line1_min)) begin
	   min_max <= line2_min;
		if(line0_min >= line1_min) begin
		  min_mid <= line0_min;
		  min_min <= line1_min;
		end 
		else begin
		  min_mid <= line1_min;
		  min_min <= line0_min;
		end
	 end
  end
end
//------------------------------------------------------------------------------
// middle
//------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
  if(!rst_n)
    mid <= 16'd0;
  else if(data_in_en) begin
    if(((max_mid >= mid_mid) && (max_mid < min_mid)) || ((max_mid >= min_mid) && (max_mid < mid_mid)))
	   mid <= max_mid;
	 else if(((mid_mid > max_mid) && (mid_mid < min_mid)) || ((min_mid >= min_mid) && (mid_mid < max_mid)))
	   mid <= mid_mid;
	 else if(((min_mid > max_mid) && (min_mid < mid_mid)) || ((min_mid > mid_mid) && (mid_min < max_mid)))
	   mid <= min_mid;
  end
  else ;
end
//------------------------------------------------------------------------------------------------------
//result
//------------------------------------------------------------------------------------------------------
assign data_out = mid;
assign data_out_en = de2;
assign hs_out = hs2;
assign vs_out = vs2;
endmodule