当前位置:   article > 正文

自适应中值滤波(FPGA实现)

自适应中值滤波

1. 算法原理流程图

自适应中值滤波硬件框图如下。
在这里插入图片描述
在这里插入图片描述

2. 5x5窗口产生

3x3窗口中值滤波参考比较多,这里不做介绍。
图像数据是一个一个输入进来的,要实现5x5的模板,就首先必须要保证能同时能对5行图像数据进行获取,这样就必须要对图像数据进行行缓存,咋一看,5x5模板需要缓存5行,其实不然,缓存4行后,接下来输入进来的数据就是第5行的数据了,这样就实现了5行数据同时存在的情况了,对行缓存区的要求是左端进入一个数据,右端出来一个数据,这个要求与移位寄存器有些类似。
5x5窗口生成
Vivado中通过调用IP核叫RAM-base Shift Register即可实现5行数据移位寄存。因为使用的是720p图像做处理,这里使用IP核串行处理来实现1280个数据(IP核内depth最大为1088)。
在这里插入图片描述

代码如下:

module shift_reg_5x5(
    input wire taps_clk             ,
    input wire[7:0] shift_in        ,
    input wire shiftin_valid        ,
    output wire[7:0] shift_out      ,
    output wire [7:0] taps3x        ,
    output wire [7:0] taps2x        ,
    output wire [7:0] taps1x        ,
    output wire [7:0] taps0x 
    );

    wire [7:0] line3;
    wire [7:0] line2;
    wire [7:0] line1;
    wire [7:0] line0;
//5x1
//5x2
c_shift_ram_0 c_shift_ram_0_u1 (
  .D(shift_in),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(line3)      // output wire [7 : 0] Q
);
c_shift_ram_0 c_shift_ram_0_u2 (
  .D(line3),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(taps3x)      // output wire [7 : 0] Q
);
//5x3
c_shift_ram_0 c_shift_ram_0_u3 (
  .D(taps3x),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(line2)      // output wire [7 : 0] Q
);
c_shift_ram_0 c_shift_ram_0_u4 (
  .D(line2),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(taps2x)      // output wire [7 : 0] Q
);
//5x4
c_shift_ram_0 c_shift_ram_0_u5 (
  .D(taps2x),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(line1)      // output wire [7 : 0] Q
);
c_shift_ram_0 c_shift_ram_0_u6 (
  .D(line1),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(taps1x)      // output wire [7 : 0] Q
);
//5x5
c_shift_ram_0 c_shift_ram_0_u7 (
  .D(taps1x),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(line0)      // output wire [7 : 0] Q
);
c_shift_ram_0 c_shift_ram_0_u8 (
  .D(line0),      // input wire [7 : 0] D
  .CLK(taps_clk),  // input wire CLK
  .CE(shiftin_valid),    // input wire CE
  .Q(taps0x)      // output wire [7 : 0] Q
);

assign shift_out = taps0x   ;
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

仿真如下,5x5窗口生成输出正确
在这里插入图片描述

3. 5x5中值滤波器实现

5x5中值输出流程如下,对某一个 5x5 的图像采样窗口,5x5中值滤波器经过两个时钟周期即可实现最大值,最小值的求取,而中值需要再经过两次对角线元素的排序才能输出,也即还需要两个时钟周期才能求取,因此实现完整的滤波器功能需要4个时钟周期。在每个步骤的排序中,每行的排序是可以并行执行的,所以完成5行降幂排序只需要一个时钟周期;每列的排序也是可以并行执行的,所以完成5列降幂排序也只需要一个时钟周期;后面的对角线排序也是一个同步时钟周期即可完成。
在这里插入图片描述
5x5中值滤波器顶层模块代码如下:

module median_filter_5
#(
    parameter DATA_WIDTH = 8
)
(
    input wire clk                      ,
    input wire reset_p                    ,
    input wire[DATA_WIDTH-1:0] 
    data_00,data_01,data_02,data_03,data_04,
    data_10,data_11,data_12,data_13,data_14,
    data_20,data_21,data_22,data_23,data_24,
    data_30,data_31,data_32,data_33,data_34,
    data_40,data_41,data_42,data_43,data_44,
    input wire data_in_valid            ,
    output wire[DATA_WIDTH-1:0] data_out_max,
    output wire[DATA_WIDTH-1:0] data_out_med,
    output wire[DATA_WIDTH-1:0] data_out_min,
    output wire[DATA_WIDTH-1:0] dout5_xy,//中心像素点
    output wire data_out_valid          
    );
//=======line data Interface ========
wire [DATA_WIDTH-1:0] l0_min,l1_min,l2_min,l3_min,l4_min;
wire [DATA_WIDTH-1:0] l0_min_next,l1_min_next,l2_min_next,l3_min_next,l4_min_next;
wire [DATA_WIDTH-1:0] l0_med,l1_med,l2_med,l3_med,l4_med;
wire [DATA_WIDTH-1:0] l0_max_next,l1_max_next,l2_max_next,l3_max_next,l4_max_next;
wire [DATA_WIDTH-1:0] l0_max,l1_max,l2_max,l3_max,l4_max;
//=======row data Interface ========
wire [DATA_WIDTH-1:0] min_min,min_next_min,med_min,max_next_min,max_min;
wire [DATA_WIDTH-1:0] min_min_next,min_next_min_next,med_min_next,max_next_min_next,max_min_next;
wire [DATA_WIDTH-1:0] min_med,min_next_med,med_med,max_next_med,max_med;
wire [DATA_WIDTH-1:0] valid_med;
wire [DATA_WIDTH-1:0] min_max_next,min_next_max_next,med_max_next,max_next_max_next,max_max_next;
wire [DATA_WIDTH-1:0] min_max,min_next_max,med_max,max_next_max,max_max;
//5x5模版排序需要四个时钟周期
reg data_in_valid_reg1  ;
reg data_in_valid_reg2  ;
reg data_in_valid_reg3  ;
reg data_in_valid_reg4  ;

reg [DATA_WIDTH-1:0] dout5_xy_reg1 ;
reg [DATA_WIDTH-1:0] dout5_xy_reg2 ;
reg [DATA_WIDTH-1:0] dout5_xy_reg3 ;
reg [DATA_WIDTH-1:0] dout5_xy_reg4 ;

always @(posedge clk ) begin
    data_in_valid_reg1<= data_in_valid      ;
    data_in_valid_reg2<= data_in_valid_reg1 ;
    data_in_valid_reg3<= data_in_valid_reg2 ;//
    data_in_valid_reg4<= data_in_valid_reg3 ;

    dout5_xy_reg1 <= data_22        ;
    dout5_xy_reg2 <= dout5_xy_reg1  ;
    dout5_xy_reg3 <= dout5_xy_reg2  ;
    dout5_xy_reg4 <= dout5_xy_reg3  ;  
end

//======= l0 排序 ========
sort5 sort5_u0(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg1),
    .i1		    (data_00),
    .i2		    (data_01),
    .i3		    (data_02),
    .i4		    (data_03),
    .i5		    (data_04),
    .dout_1	    (l0_min      ), 
    .dout_2	    (l0_min_next ), //临近min的值
    .dout_3	    (l0_med      ),    
    .dout_4	    (l0_max_next ), //临近max的值
    .dout_5	    (l0_max      ),
    .dout_valid () 
    );
//======= l1 排序 ========
sort5 sort5_u1(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg1),
    .i1		    (data_10),
    .i2		    (data_11),
    .i3		    (data_12),
    .i4		    (data_13),
    .i5		    (data_14),
    .dout_1	    (l1_min      ), 
    .dout_2	    (l1_min_next ), //临近min的值
    .dout_3	    (l1_med      ),    
    .dout_4	    (l1_max_next ), //临近max的值
    .dout_5	    (l1_max      ),
    .dout_valid () 
    );
//======= l2 排序 ========
sort5 sort5_u2(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg1),
    .i1		    (data_20),
    .i2		    (data_21),
    .i3		    (data_22),
    .i4		    (data_23),
    .i5		    (data_24),
    .dout_1	    (l2_min      ), 
    .dout_2	    (l2_min_next ), //临近min的值
    .dout_3	    (l2_med      ),    
    .dout_4	    (l2_max_next ), //临近max的值
    .dout_5	    (l2_max      ),
    .dout_valid () 
    );
//======= l3 排序 ========
sort5 sort5_u3(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg1),
    .i1		    (data_30),
    .i2		    (data_31),
    .i3		    (data_32),
    .i4		    (data_33),
    .i5		    (data_34),
    .dout_1	    (l3_min      ), 
    .dout_2	    (l3_min_next ), //临近min的值
    .dout_3	    (l3_med      ),    
    .dout_4	    (l3_max_next ), //临近max的值
    .dout_5	    (l3_max      ),
    .dout_valid () 
    );
//======= l4 排序 ========
sort5 sort5_u4(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg1),
    .i1		    (data_40),
    .i2		    (data_41),
    .i3		    (data_42),
    .i4		    (data_43),
    .i5		    (data_44),
    .dout_1	    (l4_min      ), 
    .dout_2	    (l4_min_next ), //临近min的值
    .dout_3	    (l4_med      ),    
    .dout_4	    (l4_max_next ), //临近max的值
    .dout_5	    (l4_max      ),
    .dout_valid () 
    );
//======= row0 排序 ========
sort5 sort5_u5(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg2),
    .i1		    (l0_min),
    .i2		    (l1_min),
    .i3		    (l2_min),
    .i4		    (l3_min),
    .i5		    (l4_min),
    .dout_1	    (min_min      ), 
    .dout_2	    (min_min_next ), //临近min的值
    .dout_3	    (min_med      ),    
    .dout_4	    (min_max_next ), //临近max的值
    .dout_5	    (min_max      ),
    .dout_valid () 
    );
//======= row1 排序 ========
sort5 sort5_u6(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg2),
    .i1		    (l0_min_next),
    .i2		    (l1_min_next),
    .i3		    (l2_min_next),
    .i4		    (l3_min_next),
    .i5		    (l4_min_next),
    .dout_1	    (min_next_min     ), 
    .dout_2	    (min_next_min_next), //临近min的值
    .dout_3	    (min_next_med     ),    
    .dout_4	    (min_next_max_next), //临近max的值
    .dout_5	    (min_next_max     ),
    .dout_valid () 
    );
//======= row2 排序 ========
sort5 sort5_u7(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg2),
    .i1		    (l0_med),
    .i2		    (l1_med),
    .i3		    (l2_med),
    .i4		    (l3_med),
    .i5		    (l4_med),
    .dout_1	    (med_min     ), 
    .dout_2	    (med_min_next), //临近min的值
    .dout_3	    (med_med     ),    
    .dout_4	    (med_max_next), //临近max的值
    .dout_5	    (med_max     ),
    .dout_valid () 
    );
//======= row3 排序 ========
sort5 sort5_u8(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg2),
    .i1		    (l0_max_next),
    .i2		    (l1_max_next),
    .i3		    (l2_max_next),
    .i4		    (l3_max_next),
    .i5		    (l4_max_next),
    .dout_1	    (max_next_min     ), 
    .dout_2	    (max_next_min_next), //临近min的值
    .dout_3	    (max_next_med     ),    
    .dout_4	    (max_next_max_next), //临近max的值
    .dout_5	    (max_next_max     ),
    .dout_valid () 
    );
//======= row4 排序 ========
sort5 sort5_u9(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg2),
    .i1		    (l0_max),
    .i2		    (l1_max),
    .i3		    (l2_max),
    .i4		    (l3_max),
    .i5		    (l4_max),
    .dout_1	    (max_min     ), 
    .dout_2	    (max_min_next), //临近min的值
    .dout_3	    (max_med     ),    
    .dout_4	    (max_max_next), //临近max的值
    .dout_5	    (max_max     ),
    .dout_valid () 
    );

//
wire [DATA_WIDTH-1:0] d14,d23,d32,d41;
wire [DATA_WIDTH-1:0] d15,d24,d33,d42,d51;
wire [DATA_WIDTH-1:0] d25,d34,d43,d52;

sort5 sort5_u10(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg3),
    .i1		    (0),
    .i2		    (min_max_next),
    .i3		    (min_next_med),
    .i4		    (med_min_next),
    .i5		    (max_next_min),
    .dout_1	    (     ), 
    .dout_2	    (d14), //临近min的值
    .dout_3	    (d23),    
    .dout_4	    (d32), //临近max的值
    .dout_5	    (d41),
    .dout_valid () 
    );

sort5 sort5_u11(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg3),
    .i1		    (min_max          ),
    .i2		    (min_next_max_next),
    .i3		    (med_med          ),
    .i4		    (max_next_min_next),
    .i5		    (max_min          ),
    .dout_1	    (d15), 
    .dout_2	    (d24), //临近min的值
    .dout_3	    (d33),    
    .dout_4	    (d42), //临近max的值
    .dout_5	    (d51),
    .dout_valid () 
    );

sort5 sort5_u12(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg3),
    .i1		    (0 ),
    .i2		    (min_next_max),
    .i3		    (med_max_next),
    .i4		    (max_next_med),
    .i5		    (max_min_next),
    .dout_1	    (), 
    .dout_2	    (d25), //临近min的值
    .dout_3	    (d34),    
    .dout_4	    (d43), //临近max的值
    .dout_5	    (d52),
    .dout_valid () 
    );

sort5 sort5_u13(
	.clk	    (clk),
	.reset_p	    (reset_p),
    .din_valid  (data_in_valid_reg4),
    .i1		    (0),
    .i2		    (0),
    .i3		    (d41),
    .i4		    (d33),
    .i5		    (d25),
    .dout_1	    (), 
    .dout_2	    (), //临近min的值
    .dout_3	    (),    
    .dout_4	    (valid_med), //临近max的值
    .dout_5	    (),
    .dout_valid () 
    );

//输出数据同步
reg [7:0] min_min_reg1,min_min_reg2;
reg [7:0] max_max_reg1,max_max_reg2;
always @(posedge clk ) begin
    min_min_reg1<=min_min;
    min_min_reg2<=min_min_reg1;

    max_max_reg1<=max_max;
    max_max_reg2<=max_max_reg1;
end

assign data_out_min = min_min_reg2   ;
assign data_out_med = valid_med ;
assign data_out_max = max_max_reg2   ;
assign dout5_xy = dout5_xy_reg4;

assign data_out_valid =data_in_valid_reg4;
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318

4. 自适应判断模块实现

注意3x3中值滤波器只需三个时钟周期即可输出中值,两个中值滤波器输入数据来自同一个 5x5 的图像采样窗口,是同步的,而处理速度不同,因此输出数据将不再同步,会影响到后面的自适应比较模块,需要对3x3中值滤波器输出数据做延迟处理。

自适应中值滤波顶层代码:

module adap_median_filter#(
    parameter DATA_WIDTH = 8
)(
    input wire clk                  ,
    input wire reset_p                  ,
    input wire [DATA_WIDTH-1:0] data_in ,
    input wire data_in_valid            ,
    input wire data_in_hs               ,
    input wire data_in_vs               ,
    
    output reg [DATA_WIDTH-1:0] data_out,
    output wire data_out_valid          ,
    output wire data_out_hs             ,
    output wire data_out_vs             
    );

//将3x3滤波器输出数据与5x5滤波器同步输出到自适应判断模块
wire [DATA_WIDTH-1:0] S3_max,S3_med,S3_min;

//S内部最大值、中值、最小值、中心点值
wire [DATA_WIDTH-1:0] S5_max,S5_med,S5_min;


// reg [2:0] S    ;   //窗口尺寸

wire [DATA_WIDTH-1:0] dout5_xy;

reg data_in_valid_reg1,data_in_valid_reg2,data_in_valid_reg3,
    data_in_valid_reg4,data_in_valid_reg5;
reg data_in_hs_reg1,data_in_hs_reg2,data_in_hs_reg3,
    data_in_hs_reg4,data_in_hs_reg5;
reg data_in_vs_reg1,data_in_vs_reg2,data_in_vs_reg3,
    data_in_vs_reg4,data_in_vs_reg5;
always@(posedge clk)
begin
    data_in_valid_reg1 <= data_in_valid;
    data_in_valid_reg2 <= data_in_valid_reg1;
    data_in_valid_reg3 <= data_in_valid_reg2;
    data_in_valid_reg4 <= data_in_valid_reg3;
    data_in_valid_reg5 <= data_in_valid_reg4;

    data_in_hs_reg1   <= data_in_hs;
    data_in_hs_reg2   <= data_in_hs_reg1;
    data_in_hs_reg3   <= data_in_hs_reg2;
    data_in_hs_reg4   <= data_in_hs_reg3;
    data_in_hs_reg5   <= data_in_hs_reg4;

    data_in_vs_reg1   <= data_in_vs;
    data_in_vs_reg2   <= data_in_vs_reg1;
    data_in_vs_reg3   <= data_in_vs_reg2;
    data_in_vs_reg4   <= data_in_vs_reg3;
    data_in_vs_reg5   <= data_in_vs_reg4; 
end

//======= 5x5 generate begin ========
wire [DATA_WIDTH-1:0] l0_data;    //第一行数据
wire [DATA_WIDTH-1:0] l1_data;
wire [DATA_WIDTH-1:0] l2_data;
wire [DATA_WIDTH-1:0] l3_data;
wire [DATA_WIDTH-1:0] l4_data;

shift_reg_5x5 shift_reg_5x5_u(
    .taps_clk     (clk     ),
    .shift_in     (data_in     ),
    .shiftin_valid(data_in_valid),
    .shift_out    (    ),
    .taps3x       (l3_data       ),
    .taps2x       (l2_data       ),
    .taps1x       (l1_data       ),
    .taps0x       (l0_data       ) 
    );
assign l4_data = data_in;
//5x5  row 1
reg [DATA_WIDTH-1:0] data_00,data_01,data_02,data_03,data_04;
reg [DATA_WIDTH-1:0] data_10,data_11,data_12,data_13,data_14;
reg [DATA_WIDTH-1:0] data_20,data_21,data_22,data_23,data_24;
reg [DATA_WIDTH-1:0] data_30,data_31,data_32,data_33,data_34;
reg [DATA_WIDTH-1:0] data_40,data_41,data_42,data_43,data_44;

always@(posedge clk or posedge reset_p)
begin
   if(reset_p)begin
    data_00 <= 8'd0;data_01 <= 8'd0;data_02 <= 8'd0;data_03 <= 8'd0;data_04 <= 8'd0;
    data_10 <= 8'd0;data_11 <= 8'd0;data_12 <= 8'd0;data_13 <= 8'd0;data_14 <= 8'd0;
    data_20 <= 8'd0;data_21 <= 8'd0;data_22 <= 8'd0;data_23 <= 8'd0;data_24 <= 8'd0;
    data_30 <= 8'd0;data_31 <= 8'd0;data_32 <= 8'd0;data_33 <= 8'd0;data_34 <= 8'd0;
    data_40 <= 8'd0;data_41 <= 8'd0;data_42 <= 8'd0;data_43 <= 8'd0;data_44 <= 8'd0;
   end
   else if (data_in_hs && data_in_vs) begin
    if (data_in_valid) begin
        data_04 <= l0_data; data_03 <= data_04; data_02 <= data_03; data_01 <= data_02; data_00 <= data_01;
        data_14 <= l1_data; data_13 <= data_14; data_12 <= data_13; data_11 <= data_12; data_10 <= data_11;
        data_24 <= l2_data; data_23 <= data_24; data_22 <= data_23; data_21 <= data_22; data_20 <= data_21;
        data_34 <= l3_data; data_33 <= data_34; data_32 <= data_33; data_31 <= data_32; data_30 <= data_31;
        data_44 <= l4_data; data_43 <= data_44; data_42 <= data_43; data_41 <= data_42; data_40 <= data_41;
    end
    else begin
        data_00 <= data_00; data_01 <= data_01; data_02 <= data_02; data_03 <= data_03; data_04 <= data_04;
        data_10 <= data_10; data_11 <= data_11; data_12 <= data_12; data_13 <= data_13; data_14 <= data_14;
        data_20 <= data_20; data_21 <= data_21; data_22 <= data_22; data_23 <= data_23; data_24 <= data_24;
        data_30 <= data_30; data_31 <= data_31; data_32 <= data_32; data_33 <= data_33; data_34 <= data_34;
        data_40 <= data_40; data_41 <= data_41; data_42 <= data_42; data_43 <= data_43; data_44 <= data_44;
    end 
    end
   else begin
    data_00 <= 8'd0;data_01 <= 8'd0;data_02 <= 8'd0;data_03 <= 8'd0;data_04 <= 8'd0;
    data_10 <= 8'd0;data_11 <= 8'd0;data_12 <= 8'd0;data_13 <= 8'd0;data_14 <= 8'd0;
    data_20 <= 8'd0;data_21 <= 8'd0;data_22 <= 8'd0;data_23 <= 8'd0;data_24 <= 8'd0;
    data_30 <= 8'd0;data_31 <= 8'd0;data_32 <= 8'd0;data_33 <= 8'd0;data_34 <= 8'd0;
    data_40 <= 8'd0;data_41 <= 8'd0;data_42 <= 8'd0;data_43 <= 8'd0;data_44 <= 8'd0;
   end
end

//======= 5x5 generate end ========
median_filter_3#(
    .DATA_WIDTH (8)
)
median_filter_3_u(
    .clk    (clk    )    ,
    .reset_p(reset_p)    ,
    .data_00(data_11),.data_01(data_12),.data_02(data_13),
    .data_10(data_21),.data_11(data_22),.data_12(data_23),
    .data_20(data_31),.data_21(data_32),.data_22(data_33),
    .data_in_valid  (data_in_valid),
    .data_out_min   (S3_min),
    .data_out_med   (S3_med),
    .data_out_max   (S3_max),
    .data_out_valid (   )
    );

median_filter_5#(
    .DATA_WIDTH  (8)
)
median_filter_5_u(
    .clk       (clk)         ,
    .reset_p   (reset_p)     , 
    .data_00(data_00),.data_01(data_01),.data_02(data_02),.data_03(data_03),.data_04(data_04),
    .data_10(data_10),.data_11(data_11),.data_12(data_12),.data_13(data_13),.data_14(data_14),
    .data_20(data_20),.data_21(data_21),.data_22(data_22),.data_23(data_23),.data_24(data_24),
    .data_30(data_30),.data_31(data_31),.data_32(data_32),.data_33(data_33),.data_34(data_34),
    .data_40(data_40),.data_41(data_41),.data_42(data_42),.data_43(data_43),.data_44(data_44),
    .data_in_valid   (data_in_valid) ,
    .data_out_max    (S5_max       ) ,
    .data_out_med    (S5_med       ) ,
    .data_out_min    (S5_min       ) ,
    .dout5_xy        (dout5_xy     ) ,//中心像素点
    .data_out_valid  (  ) 
    );

//======= adaptive logical begin ========
always@(posedge clk or posedge reset_p)
begin
   if(reset_p)begin
    data_out<=8'd0;
   end
   else if(data_in_valid)begin
    if((S5_med==S5_max)||(S5_med==S5_min)) begin
        if ((S3_med==S3_max)||(S3_med==S3_min)) begin
            data_out<=S5_med;
        end
        else begin
            if ((dout5_xy==S3_max)||(dout5_xy==S3_min)) begin
                data_out<=S3_med;
            end
            else
                data_out<=dout5_xy;
        end
    end
    else begin
        if ((dout5_xy==S5_max)||(dout5_xy==S5_min)) begin
            data_out <= S5_med;
        end
        else
            data_out<= dout5_xy;
    end
   end               
end

assign data_out_valid = data_in_valid_reg4;
assign data_out_hs = data_in_hs_reg4;
assign data_out_vs = data_in_vs_reg4;

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183

仿真结果如下,滤波器输出数据进行了同步,并进行自适应判断
在这里插入图片描述

5. 处理效果

如下图,1图为含有10%浓度椒盐噪声的灰度图,2图为含有30%浓度椒盐噪声的灰度图,3图含有50%浓度椒盐噪声的灰度图,4图为原始灰度图。
在这里插入图片描述
3x3中值滤波器处理效果图
在这里插入图片描述
5x5中值滤波器处理效果图
在这里插入图片描述
自适应中值滤波处理
在这里插入图片描述
以上仅供参考(作为学习记录)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/773048
推荐阅读
相关标签
  

闽ICP备14008679号