一、均值和中值濾波基本原理
首先要做的是最簡(jiǎn)單的均值濾波算法。均值濾波是典型的線性濾波算法,它是指在圖像上對(duì)目標(biāo)像素給一個(gè)模板,該模板包括了其周圍的臨近像素(以目標(biāo)象素為中心的周圍 8 個(gè)像素,構(gòu)成一個(gè)濾波模板,即去掉目標(biāo)像素本身),再用模板中的全體像素的平均值來(lái)代替原來(lái)像素值。中值濾波算法可以形象的用上述表格來(lái)描述,即對(duì)于每個(gè) 33 的陣列而言,中間像素的值,等于邊緣 8 個(gè)像素的平均值。
無(wú)論是直接獲取的灰度圖像,還是由彩色圖像轉(zhuǎn)換得到的灰度圖像,里面都有噪聲的存在,噪聲對(duì)圖像質(zhì)量有很大的影響。進(jìn)行中值濾波不僅可以去除孤點(diǎn)噪聲,而且可以保持圖像的邊緣特性,不會(huì)使圖像產(chǎn)生顯著的模糊,比較適合于實(shí)驗(yàn)中的人臉圖像。中值濾波算法與均值濾波非常的相似,但濾波的效果卻有很大的差別,區(qū)別如下:(1) 均值濾波相當(dāng)于低通濾波,有將圖像模糊化的趨勢(shì),對(duì)椒鹽噪聲基本無(wú)能力。(2) 中值濾波的有點(diǎn)事可以很好的過(guò)濾椒鹽噪聲,缺點(diǎn)是容易造成圖像的不連續(xù)。中值濾波的算法非常簡(jiǎn)單,只要求得 33 像素陣列的中間值即可,這樣就有效的移植了最大值與最小值,圖像會(huì)變得均勻,對(duì)椒鹽噪聲有很好的濾除效果!
《基于FPGA的實(shí)時(shí)中值濾波器的硬件實(shí)現(xiàn)》這篇文章中介紹了一種適合FPGA實(shí)現(xiàn)的快速尋找中值的算法,算法過(guò)程是這樣的:首先計(jì)算每一行的最大值、中值以及最小值;之后計(jì)算第一列最大值中的最小值,第二列中間值中的中間值,第三列最小值中的最大值;最后再次計(jì)算這三個(gè)值的中間值就可以得到中值了。
二、3×3圖像矩陣的提取
可以發(fā)現(xiàn),無(wú)論是均值濾波還是中值濾波,一個(gè)必要的步驟就是得到3×3的圖像矩陣。這個(gè)圖像矩陣在matlab中很容易得到,因?yàn)閙atlab讀取的是整一張的圖片。但是在FPGA中對(duì)圖像的實(shí)時(shí)處理,則需要先緩存兩到三行的數(shù)據(jù),然后從這3行數(shù)據(jù)中獲得3×3圖像矩陣。
查閱了一些資料,發(fā)現(xiàn)在VIVADO中實(shí)現(xiàn)3×3矩陣有以下幾種方法。(1)第一種是利用vivado的IP核:ram based shift register,這個(gè)ip核在緩存數(shù)據(jù)量小的時(shí)候可以用。但是數(shù)據(jù)量很大,為幾百個(gè)以上的時(shí)候,緩存數(shù)量就不準(zhǔn)了,不知道是不是bug,因此不推薦使用。(2)第二種是利用RAM(3)第三種是利用fifo實(shí)現(xiàn),利用fifo實(shí)現(xiàn)野火教程很詳細(xì)。我這邊是利用了兩個(gè)ram實(shí)現(xiàn)數(shù)據(jù)的緩存和3×3矩陣的提取,接下來(lái)介紹實(shí)現(xiàn)過(guò)程。
2.1、例化ram ip核
首先自然是先需要例化一個(gè)ram的IP核,這個(gè)ram的配置信息如下如所示,是一個(gè)雙端口的ram,寬度8位,深度1024位,優(yōu)先寫(xiě)操作。詳細(xì)的可以看配置的圖。
2.2、基于ram的移位寄存器
基于ram 的移位寄存器代碼如下圖所示。輸入端口有時(shí)鐘信號(hào)、時(shí)鐘使能信號(hào)、行同步信號(hào)、數(shù)據(jù)輸入信號(hào)。輸出端口有前一行數(shù)據(jù)、前前一行的數(shù)據(jù)。具體實(shí)現(xiàn)是這樣的,當(dāng)行同步和時(shí)鐘使能到來(lái)時(shí),地址開(kāi)始累加了,當(dāng)行同步結(jié)束,地址清零。之后對(duì)時(shí)鐘信號(hào)、地址信號(hào)、數(shù)據(jù)信號(hào)都延遲三拍。最后兩個(gè)ram分別存儲(chǔ)了前一行和前前一行的圖像。
比較關(guān)鍵的一點(diǎn)是,ram是先開(kāi)始讀,延遲幾個(gè)時(shí)鐘后才開(kāi)始寫(xiě),因?yàn)閯傞_(kāi)始是讀不到數(shù)據(jù)的,只有下一個(gè)行同步信號(hào)來(lái)的時(shí)候,前一行數(shù)據(jù)才會(huì)被讀出來(lái),這里比較繞。
module line_shift_RAM_8bit1(
input clock,
input clken,
input per_frame_href,
input [7:0] shiftin, //當(dāng)前行的數(shù)據(jù)
output [7:0] taps0x, //前一行的數(shù)據(jù)
output [7:0] taps1x //前前一行的數(shù)據(jù)
);
//reg define
reg [2:0] clken_dly;
reg [9:0] ram_rd_addr;
reg [9:0] ram_rd_addr_d0;
reg [9:0] ram_rd_addr_d1;
reg [9:0] ram_rd_addr_d2;
reg [7:0] shiftin_d0;
reg [7:0] shiftin_d1;
reg [7:0] shiftin_d2;
reg [7:0] taps0x_d0;
//在數(shù)據(jù)到來(lái)時(shí),RAM的讀地址累加
always@(posedge clock)begin
if(per_frame_href)
if(clken)
ram_rd_addr <= ram_rd_addr + 1 ;
else
ram_rd_addr <= ram_rd_addr ;
else
ram_rd_addr <= 0 ;
end
//對(duì)時(shí)鐘延遲3拍
always@(posedge clock) begin
clken_dly <= { clken_dly[1:0] , clken };
end
//將RAM地址延遲3拍
always@(posedge clock ) begin
ram_rd_addr_d0 <= ram_rd_addr;
ram_rd_addr_d1 <= ram_rd_addr_d0;
ram_rd_addr_d2 <= ram_rd_addr_d1;
end
//輸入數(shù)據(jù)延遲3拍送入RAM
always@(posedge clock)begin
shiftin_d0 <= shiftin;
shiftin_d1 <= shiftin_d0;
shiftin_d2 <= shiftin_d1;
end
//用于存儲(chǔ)前一行圖像的RAM
blk_mem_gen_0 u_ram_1024x8_0(
.clka (clock),
.wea (clken_dly[2]),
.addra (ram_rd_addr_d2), //在延遲的第三個(gè)時(shí)鐘周期,當(dāng)前行的數(shù)據(jù)寫(xiě)入RAM0
.dina (shiftin_d2),
.clkb (clock),
.addrb (ram_rd_addr),
.doutb (taps0x) //延遲一個(gè)時(shí)鐘周期,輸出RAM0中前一行圖像的數(shù)據(jù)
);
//寄存前一行圖像的數(shù)據(jù)
always@(posedge clock)begin
taps0x_d0 <= taps0x;
end
//用于存儲(chǔ)前前一行圖像的RAM
blk_mem_gen_0 u_ram_1024x8_1(
.clka (clock),
.wea (clken_dly[1]),
.addra (ram_rd_addr_d1),
.dina (taps0x_d0), //在延遲的第二個(gè)時(shí)鐘周期,將前一行圖像的數(shù)據(jù)寫(xiě)入RAM1
.clkb (clock),
.addrb (ram_rd_addr),
.doutb (taps1x) //延遲一個(gè)時(shí)鐘周期,輸出RAM1中前前一行圖像的數(shù)據(jù)
);
endmodule
我這邊結(jié)合仿真說(shuō)一下,當(dāng)clken[2]信號(hào)為高時(shí),開(kāi)始往里邊寫(xiě)信號(hào),可以看到第一次是把十六進(jìn)制51寫(xiě)到了地址0中,但是可以發(fā)現(xiàn)讀地址是已經(jīng)到了3了,所以讀速度是比寫(xiě)速度快了三個(gè)時(shí)鐘周期,因?yàn)橄乱粋€(gè)行同步來(lái)時(shí)才可以得到上一行數(shù)據(jù)。
可以看到,下面這張圖就是下一個(gè)行同步時(shí)間內(nèi),下一行數(shù)據(jù)從taps0x中讀了出來(lái)。taps1x也是同樣的道理,這邊不在敘述。
2.3、3×3圖像矩陣提取
3×3圖像矩陣提取的代碼如下圖所示,代碼本身比較簡(jiǎn)單,就是將輸入信號(hào)緩存,然后提取出矩陣。這里需要注意信號(hào)的同步,得到3×3矩陣信號(hào)要比進(jìn)來(lái)的信號(hào)慢了兩個(gè)時(shí)鐘周期。所以需要延遲兩拍。
module VIP_matrix_generate
(
input clk,
input rst_n,
input per_frame_vsync,
input per_frame_href,
input per_frame_clken,
input [7:0] per_img_Y,
output matrix_frame_vsync,
output matrix_frame_href,
output matrix_frame_clken,
output reg [7:0] matrix_p11,
output reg [7:0] matrix_p12,
output reg [7:0] matrix_p13,
output reg [7:0] matrix_p21,
output reg [7:0] matrix_p22,
output reg [7:0] matrix_p23,
output reg [7:0] matrix_p31,
output reg [7:0] matrix_p32,
output reg [7:0] matrix_p33
);
//wire define
wire [7:0] row1_data;
wire [7:0] row2_data;
wire read_frame_href ;
wire read_frame_clken;
//reg define
reg [7:0] row3_data;
reg [1:0] per_frame_vsync_r;
reg [1:0] per_frame_href_r;
reg [1:0] per_frame_clken_r;
assign read_frame_href = per_frame_href_r[0] ;
assign read_frame_clken = per_frame_clken_r[0];
assign matrix_frame_vsync = per_frame_vsync_r[1];
assign matrix_frame_href = per_frame_href_r[1] ;
assign matrix_frame_clken = per_frame_clken_r[1];
//present signal
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
row3_data <= 0;
else begin
if(per_frame_clken)
row3_data <= per_img_Y ;
else
row3_data <= row3_data ;
end
end
line_shift_RAM_8bit1 u_line_shift_RAM_8bit1(
.clock ( clk ),
.clken ( per_frame_clken ),
.per_frame_href ( per_frame_href ),
.shiftin ( per_img_Y ),
.taps0x ( row2_data ),
.taps1x ( row1_data )
);
//delay 2 tclk
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
per_frame_clken_r <= 0;
end
else begin
per_frame_vsync_r <= { per_frame_vsync_r[0], per_frame_vsync };
per_frame_href_r <= { per_frame_href_r[0], per_frame_href };
per_frame_clken_r <= { per_frame_clken_r[0], per_frame_clken };
end
end
//generate the 3X3 matrix
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
{matrix_p11, matrix_p12, matrix_p13} <= 24'h0;
{matrix_p21, matrix_p22, matrix_p23} <= 24'h0;
{matrix_p31, matrix_p32, matrix_p33} <= 24'h0;
end
else if(read_frame_href) begin
if(read_frame_clken) begin
{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data};
{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data};
{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data};
end
else begin
{matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13};
{matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23};
{matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33};
end
end
else begin
{matrix_p11, matrix_p12, matrix_p13} <= 24'h0;
{matrix_p21, matrix_p22, matrix_p23} <= 24'h0;
{matrix_p31, matrix_p32, matrix_p33} <= 24'h0;
end
end
endmodule
仿真的結(jié)果如下面三張圖所示,當(dāng)pei_img_Y數(shù)據(jù)來(lái)到的時(shí)候,延遲兩個(gè)時(shí)鐘周期進(jìn)入到row3_data中,之后在延遲一個(gè)周期數(shù)據(jù)送到p31、p32以及p33中。row2_data和row1_data的得到也是同樣的原理。
三、均值濾波的實(shí)現(xiàn)
前面已經(jīng)清楚描述了均值濾波的實(shí)現(xiàn)過(guò)程,主要就是將圖像像素點(diǎn)周圍8個(gè)像素的值加起來(lái)然后除以8就可以了,下面式均值濾波的實(shí)現(xiàn)代碼。
module mean_filter(
input clk,
input rst_n,
input [23:0] pre_data,
input per_vsync,
input per_href,
input per_clken,
output [23:0] post_data,
output post_vsync,
output post_href,
output post_clken
);
//-----------------------------
//generate 3×3 picture matrix
//-----------------------------
wire matrix_frame_clken;
wire matrix_frame_href;
wire matrix_frame_vsync;
wire [7:0] matrix_p11;
wire [7:0] matrix_p12;
wire [7:0] matrix_p13;
wire [7:0] matrix_p21;
wire [7:0] matrix_p22;
wire [7:0] matrix_p23;
wire [7:0] matrix_p31;
wire [7:0] matrix_p32;
wire [7:0] matrix_p33;
VIP_matrix_generate u_VIP_matrix_generate(
.clk ( clk ),
.rst_n ( rst_n ),
.per_frame_vsync ( per_vsync ),
.per_frame_href ( per_href ),
.per_frame_clken ( per_clken ),
.per_img_Y ( pre_data[7:0] ),
.matrix_frame_vsync ( matrix_frame_vsync ),
.matrix_frame_href ( matrix_frame_href ),
.matrix_frame_clken ( matrix_frame_clken ),
.matrix_p11 ( matrix_p11 ),
.matrix_p12 ( matrix_p12 ),
.matrix_p13 ( matrix_p13 ),
.matrix_p21 ( matrix_p21 ),
.matrix_p22 ( matrix_p22 ),
.matrix_p23 ( matrix_p23 ),
.matrix_p31 ( matrix_p31 ),
.matrix_p32 ( matrix_p32 ),
.matrix_p33 ( matrix_p33 )
);
//-----------------------------
//mean filter function
//-----------------------------
reg [11:0] add_p1;
reg [11:0] add_p2;
reg [11:0] add_p3;
reg [11:0] add_all;
//step1:add every href
always @(posedge clk or negedge rst_n) begin
if(~rst_n)begin
add_p1<=12'd0;
add_p2<=12'd0;
add_p3<=12'd0;
end
else begin
add_p1<=matrix_p11+matrix_p12+matrix_p13;
add_p2<=matrix_p21+matrix_p23;
add_p3<=matrix_p31+matrix_p32+matrix_p33;
end
end
//step2:add all the data
always @(posedge clk or negedge rst_n) begin
if(~rst_n)begin
add_all<=12'd0;
end
else begin
add_all<=add_p1+add_p2+add_p3;
end
end
//step3:shift to get mean filter data
assign post_data={3{add_all[10:3]}};
//-----------------------------
//clk signal synchronization
//-----------------------------
reg [1:0] post_clken_dy;
reg [1:0] post_href_dy;
reg [1:0] post_vsync_dy;
always @(posedge clk or negedge rst_n) begin
if(~rst_n)begin
post_clken_dy<=2'd0;
post_href_dy<=2'd0;
post_vsync_dy<=2'd0;
end
else begin
post_clken_dy<={post_clken_dy[0],matrix_frame_clken};
post_href_dy<={post_href_dy[0],matrix_frame_href};
post_vsync_dy<={post_vsync_dy[0],matrix_frame_vsync};
end
end
assign post_clken=post_clken_dy[1];
assign post_href=post_href_dy[1];
assign post_vsync=post_vsync_dy[1];
endmodule
然后下面兩張圖分別是我用vivado仿真的加了椒鹽噪聲之后的圖片以及均值濾波之后的圖片??梢园l(fā)現(xiàn),均值濾波片讓圖片變得模糊了,而且椒鹽噪聲也沒(méi)有有效濾除。這邊的vivado仿真圖像處理是用verilog去模擬了攝像頭的產(chǎn)生時(shí)序,實(shí)現(xiàn)過(guò)程是參考了b站up主大磊FPGA。
四、中值濾波的實(shí)現(xiàn)
中值濾波的實(shí)現(xiàn)和均值濾波相似,也是需要先提取3×3的圖像矩陣,然后提取9個(gè)值中的中值,提取的方法在上面也講到了。
首先下面是對(duì)三個(gè)輸出信號(hào)進(jìn)行排序的代碼,分別排序并且輸出最大值,中間值以及最小值。
module sort_three(
input clk,
input rst_n,
input [7:0] data1,
input [7:0] data2,
input [7:0] data3,
output reg [7:0] max_data,
output reg [7:0] mid_data,
output reg [7:0] min_data
);
//find max,mid and min data
//one clk to finish
always @(posedge clk or negedge rst_n) begin
if(~rst_n)begin
max_data<=8'd0;
mid_data<=8'd0;
min_data<=8'd0;
end
else if (data1>=data2 && data2>=data3)begin
max_data<=data1;
mid_data<=data2;
min_data<=data3;
end
else if (data1>=data3 && data3>=data2)begin
max_data<=data1;
mid_data<=data3;
min_data<=data2;
end
else if (data2>=data1 && data1>=data3)begin
max_data<=data2;
mid_data<=data1;
min_data<=data3;
end
else if (data2>=data3 && data3>=data1)begin
max_data<=data2;
mid_data<=data3;
min_data<=data1;
end
else if (data3>=data1 && data1>=data2)begin
max_data<=data3;
mid_data<=data1;
min_data<=data2;
end
else if (data3>=data2 && data2>=data1)begin
max_data<=data3;
mid_data<=data2;
min_data<=data1;
end
end
endmodule
之后是中值濾波的代碼,這部分實(shí)現(xiàn)的原理就是上文說(shuō)到的提取中值的過(guò)程。
module median_filter(
input clk,
input rst_n,
input [23:0] per_data,
input per_vsync,
input per_href,
input per_clken,
output [23:0] post_data,
output post_vsync,
output post_href,
output post_clken
);
//-----------------------------
//generate 3×3 picture matrix
//-----------------------------
wire matrix_frame_clken;
wire matrix_frame_href;
wire matrix_frame_vsync;
reg [2:0] post_clken_dy;
reg [2:0] post_href_dy;
reg [2:0] post_vsync_dy;
wire [7:0] matrix_p11;
wire [7:0] matrix_p12;
wire [7:0] matrix_p13;
wire [7:0] matrix_p21;
wire [7:0] matrix_p22;
wire [7:0] matrix_p23;
wire [7:0] matrix_p31;
wire [7:0] matrix_p32;
wire [7:0] matrix_p33;
VIP_matrix_generate u_VIP_matrix_generate(
.clk ( clk ),
.rst_n ( rst_n ),
.per_frame_vsync ( per_vsync ),
.per_frame_href ( per_href ),
.per_frame_clken ( per_clken ),
.per_img_Y ( per_data[7:0] ),
.matrix_frame_vsync ( matrix_frame_vsync ),
.matrix_frame_href ( matrix_frame_href ),
.matrix_frame_clken ( matrix_frame_clken ),
.matrix_p11 ( matrix_p11 ),
.matrix_p12 ( matrix_p12 ),
.matrix_p13 ( matrix_p13 ),
.matrix_p21 ( matrix_p21 ),
.matrix_p22 ( matrix_p22 ),
.matrix_p23 ( matrix_p23 ),
.matrix_p31 ( matrix_p31 ),
.matrix_p32 ( matrix_p32 ),
.matrix_p33 ( matrix_p33 )
);
//---------------------------------------------------
// midian filter function
//---------------------------------------------------
//[a11 a12 a13] [max1 med1 min1]
//[a21 a22 a23] to [max2 med2 min2]
//[a31 a32 a33] [max3 med3 min3]
// to
// [min_of_max med_of_med max_of_min]
// to
// [med]
wire [7:0] max_data_1;
wire [7:0] mid_data_1;
wire [7:0] min_data_1;
wire [7:0] max_data_2;
wire [7:0] mid_data_2;
wire [7:0] min_data_2;
wire [7:0] max_data_3;
wire [7:0] mid_data_3;
wire [7:0] min_data_3;
wire [7:0] max_data_4;
wire [7:0] mid_data_4;
wire [7:0] min_data_4;
wire [7:0] max_data_5;
wire [7:0] mid_data_5;
wire [7:0] min_data_5;
wire [7:0] max_data_6;
wire [7:0] mid_data_6;
wire [7:0] min_data_6;
wire [7:0] max_data_7;
wire [7:0] mid_data_7;
wire [7:0] min_data_7;
//step1:every line find max,mid and min data
sort_three u_sort_three_1(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( matrix_p11 ),
.data2 ( matrix_p12 ),
.data3 ( matrix_p13 ),
.max_data ( max_data_1 ),
.mid_data ( mid_data_1 ),
.min_data ( min_data_1 )
);
sort_three u_sort_three_2(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( matrix_p21 ),
.data2 ( matrix_p22 ),
.data3 ( matrix_p23 ),
.max_data ( max_data_2 ),
.mid_data ( mid_data_2 ),
.min_data ( min_data_2 )
);
sort_three u_sort_three_3(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( matrix_p31 ),
.data2 ( matrix_p32 ),
.data3 ( matrix_p33 ),
.max_data ( max_data_3 ),
.mid_data ( mid_data_3 ),
.min_data ( min_data_3 )
);
//step2:every line find min_of_max,med_of_med,max_of_min
sort_three u_sort_three_4(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( max_data_1 ),
.data2 ( max_data_2 ),
.data3 ( max_data_3 ),
.max_data ( max_data_4 ),
.mid_data ( mid_data_4 ),
.min_data ( min_data_4 )
);
sort_three u_sort_three_5(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( mid_data_1 ),
.data2 ( mid_data_2 ),
.data3 ( mid_data_3 ),
.max_data ( max_data_5 ),
.mid_data ( mid_data_5 ),
.min_data ( min_data_5 )
);
sort_three u_sort_three_6(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( min_data_1 ),
.data2 ( min_data_2 ),
.data3 ( min_data_3 ),
.max_data ( max_data_6 ),
.mid_data ( mid_data_6 ),
.min_data ( min_data_6 )
);
//step3:find median value
sort_three u_sort_three_7(
.clk ( clk ),
.rst_n ( rst_n ),
.data1 ( min_data_4 ),
.data2 ( mid_data_5 ),
.data3 ( max_data_6 ),
.max_data ( max_data_7 ),
.mid_data ( mid_data_7 ),
.min_data ( min_data_7 )
);
assign post_data={3{mid_data_7}};
//-----------------------------
// signal synchronization
//-----------------------------
assign post_clken=post_clken_dy[2];
assign post_href=post_href_dy[2];
assign post_vsync=post_vsync_dy[2];
always @(posedge clk or negedge rst_n) begin
if(~rst_n)begin
post_clken_dy<=3'd0;
post_href_dy<=3'd0;
post_vsync_dy<=3'd0;
end
else begin
post_clken_dy<={post_clken_dy[1:0],matrix_frame_clken};
post_href_dy<={post_href_dy[1:0],matrix_frame_href};
post_vsync_dy<={post_vsync_dy[1:0],matrix_frame_vsync};
end
end
endmodule
接下來(lái)是中值濾波的仿真結(jié)果,我打個(gè)比方,比如下面69這個(gè)數(shù)值是輸出的中值。獲得中值需要消耗三個(gè)時(shí)鐘周期,因此矩陣數(shù)據(jù)比中值要快三個(gè)時(shí)鐘周期,所以和這個(gè)中值對(duì)應(yīng)的矩陣數(shù)據(jù)是:36、36、36、d7、bc、36、ff、f5、69。對(duì)應(yīng)中值就是69,這邊顯示696969是把8位數(shù)據(jù)拼接成了24位的。
最后給出的這三張圖片一次是加了椒鹽噪聲的RGB圖片,均值濾波后的圖片以及中值濾波后的圖片??梢悦黠@看到,中值濾波對(duì)椒鹽噪聲的濾除作用明顯。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-472595.html
五、總結(jié)
均值濾波和中值濾波是圖像處理的基本操作,主要核心都是提取3×3的圖像矩陣。因?yàn)楝F(xiàn)在的攝像頭含噪聲很少,所有沒(méi)有放到FPGA開(kāi)發(fā)板中進(jìn)行測(cè)試,只是對(duì)其進(jìn)行了matlab和vivado的仿真。后面做完這部分基礎(chǔ)的圖像處理后我整理下代碼并供大家參考。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-472595.html
到了這里,關(guān)于ZYNQ圖像處理(6)——均值濾波和中值濾波的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!