基於FPGA的小波變換算法的實現

 

1、5/3離散小波變換的原理

標準的提升小波過程主要包括分裂(split)、預測(predict)、更新(update)步驟,其實現的結構圖如下圖所示。

      (1)分裂就是將信號分解成數據相關的集合,效果越好的分裂其分裂的數據相關性越強。小波基的不同相當於分裂的方式不同,在本文的設計中我採用的惰性分裂將數據分離成奇偶序列x(2n)和x(2n+1)。惰性分裂是小波變換硬件實現的一種常見的分裂方式。

      (2)分裂使得兩個數據集合具有很好的相關性,考慮其相關性,使用奇序列通過一個預測算子P(.)來預測偶序列,預測誤差定義爲D(n),D(n)通過下式求得。

                                                              

通過預測能夠幫助我們消除分裂後的冗餘信息,使數據表達得更加緊緻。預測的過程往往是可逆的,在預測算子確定的情況下,便可以通過下式來恢復。此外,高頻信息也將在預測的過程中被分解出來,即就是信號的高頻分量。

                                                                

      (3)預測後獲得了信號的高頻信息,但是低頻信息並沒有獲取到,爲了保留信號的完整性。需要利用預測後的數據和來獲得一組信號的低頻信息數據。低頻信息通過一個固定的更新算子來獲得,如下式所示。

                                                                          

        綜上可知,提升算法將原始的小波變換分解爲分裂、預測、更新等比較簡單的、易於實現的步驟。這寫步驟還是可逆的,我們只需改變相應的符號和數據的流向便可以重構實現小波逆變換。

       5/3整數提升小波的預測式和更新式如式下所示。

                                     

利用提升變換原理得到反預測和反更新式如下所示。

                                      

      

2、邊界延拓

     離散小波變換時,我們一般不考慮邊界問題,認爲信號是無限長的序列,但是對於有限大小的離散二維圖像往往是有邊界的,爲了防止小波變換在邊界處發生邊界效應(濾波器截去一部分後再進行小波變換),我們常常對二維的圖像數據進行邊界延拓以消除邊界效應。零延拓、週期延拓、對稱延拓是常用的邊界延拓方法。爲了降低邊緣效應,在本設計中我採用的是對稱延拓的方法。

       對稱延拓,就是以兩端的數據爲對稱點,做對稱延拓,由於圖像數據行列均爲偶數,所以在行列數據的首延拓兩個數據,尾延拓一個數據。對稱延拓不僅能很好的保留邊界的連續性,而且實現方法比較簡單。

                 

3、5/3離散小波正變換

module column_dwt( clk, rst_n, data_c_in, dv_c_in, dv_l_out, dv_h_out, data_h, data_l );
	
	input wire clk;             //系統時鐘
	input wire rst_n;           //系統復位信號
	input wire dv_c_in;         //輸入數據有效信號,高電平器件輸入的數據有效
	input wire [7:0] data_c_in; //輸入延拓後的數據   
	
	output reg dv_h_out;        //高頻輸出有效時置高
	output reg dv_l_out;        //低頻輸出有效時置高
	output reg signed [9:0] data_h;    //列變換後的高頻信息輸出 
	output reg signed [9:0] data_l;    //列變換後的低頻信息輸出 
	
	
	/************通過兩個D觸發器將奇偶序列分開************/
	reg signed [9:0] data_one;		//數據1
	reg signed [9:0] data_two;		//數據2
	reg signed [9:0] data_three;	//數據3
	reg [8:0] data_cnt;     //輸入數據計數
	
	/************通過兩個D觸發器將奇偶序列分開************/
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin  
			data_one <= 10'd0;
			data_two <= 10'd0;
			data_three <= 10'd0;
			data_cnt <= 9'd0;
		end
		else begin
			if(dv_c_in)begin
				data_cnt <= data_cnt + 1'b1;
				data_three <= {1'b0,1'b0,data_c_in};
				data_two <= data_three;
				data_one <= data_two;
			end
			else begin
				data_cnt <= 9'd0;
				data_one <= 10'd0;
				data_two <= 10'd0;  
				data_three <= 10'd0;
			end   
		end
	end
	
	/************預測模塊:產生高頻分量************/
	reg dv_h_flag;
	reg signed [9:0] update_in;
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			data_h <= 10'd0;
			dv_h_out <= 1'b0;
			dv_h_flag <= 1'b0;
			update_in <= 10'b0;
		end
		else begin
			if(data_cnt == 9'd3)begin
				dv_h_out <= 1'b1;
				dv_h_flag <= 1'b1;
				update_in <= predict_data(data_one, data_two, data_three);
				data_h <= predict_data(data_one, data_two, data_three);
			end
			else if((data_cnt != 9'd1)&&(data_cnt != 9'd3)&&(data_cnt%2 == 1'b1))begin
				data_h <= predict_data(data_one, data_two, data_three);
				update_in <= predict_data(data_one, data_two, data_three);
			end
			else if((data_cnt%2 == 1'b0)&&(data_cnt != 9'd2)&&(data_cnt != 9'd0))begin
				update_in <= data_two;
			end
			else if(data_cnt == 9'd0)begin
				if(dv_h_flag)begin
					dv_h_out <= dv_h_out;
					dv_h_flag <= 1'b0;
					data_h <= data_h;
				end
				else begin
					dv_h_out <= 1'b0;
					data_h <= 10'd0;
				end
				update_in <= 10'd0;
			end
		end
	end
	
	/************更新控制模塊:產生低頻信息************/
	reg [8:0] update_cnt;
	reg signed [9:0] updata_one;
	reg signed [9:0] updata_two;
	reg signed [9:0] updata_three;
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			update_cnt <= 9'd0;
			updata_one <= 9'd0;
			updata_two <= 9'd0;
			updata_three <= 9'd0;
		end
		else begin
			if(dv_h_out)begin
				updata_three <= update_in;
				updata_two <= updata_three;
				updata_one <= updata_two;
				update_cnt <= update_cnt + 1'b1;
			end
			else begin
				update_cnt <= 9'd0;
				updata_one <= 9'd0;
				updata_two <= 9'd0;
				updata_three <= 9'd0;
			end
		end
	end
	
	/************更新模塊************/
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			data_l <= 10'd0;
			dv_l_out <= 1'b0;
		end
		else begin
			if(update_cnt == 9'd3)begin
				dv_l_out <= 1'b1;
				data_l <= updata_data(updata_one, updata_two, updata_three);
			end
			else if((update_cnt != 9'd1)&&(update_cnt != 9'd3)&&(update_cnt%2 == 1'b1))begin
				data_l <= updata_data(updata_one, updata_two, updata_three);
			end
			else if(update_cnt == 9'd0)begin
				dv_l_out <= 1'b0;
				data_l <= 10'd0; 
			end
		end
	end
	
	/************預測函數************/
	function signed [9:0] predict_data;
	
		input signed [9:0] one;
		input signed [9:0] two;
		input signed [9:0] three;
		
		predict_data = two - {(one + three) >> 1};
	endfunction
	
	/************更新函數************/
	
	function signed [9:0] updata_data;
	
		input signed [9:0] one;
		input signed [9:0] two;
		input signed [9:0] three;
		reg [9:0] sum;
		begin
			sum = one + three + 10'd2;
			
			if(!sum[9])begin
				updata_data = two + {(one + three + 10'd2) >> 2};
			end
			else begin
				updata_data = two - {(~(one + three + 10'd2) + 10'd1) >> 2};
			end
		end
	endfunction
	
endmodule

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章