基于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

 

 

 

 

 

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