快速傅里叶算法分析与实现

1、直接计算DFT的问题


     设x(n)为N点有限长序列,其DFT为:

一般来说,x(n)和都是复数,X(k)也是复数,。因此每计算一个X(k)值,需要N次复数乘法以及(N-1)次复数加法。而X(k)一共有N个点,所以完成整个DFT运算总共需要次复数乘法及N(N-1)次复数加法。N=4时,有:

      
          共需16次乘法,12次加法。 一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法 。因此每运算一个X(k)需 要4N次实数乘法及2N+2(N-1)=2(2N-1)次实数加 法。所以整个DFT运算总共需要     次实数乘法和  次加法。 例如:N=1024时,DFT需要复乘1,048,576次。所 以,直接计算DFT对实时性很强的信号处理来说, 对计算速度要求是太高了。

2、直接计算DFT的改进途径

      仔细观察DFT的运算就可以看出,利用系数的以下固有特性,就可以减小DFT的运算量:

1、  的周期性 
     ,符号表示取nk除以N所得之余数。

    此特性的另一种表达式为:

2、的对称性
因为  ,于是得到


这样,(1)利用这些特性,使DFT运算中有些项可以合并;

(2)利用的对称性和周期性,可以将长序列的DFT分解为短序列的DFT。前面已经说过,DFT的运算量与成正比,所以N越小越有利。


快速傅立叶变换就是在这种思路下发展起来的。下面将详细介绍。


3、FFT(快速傅里叶)算法

       

FFT算法的基本思想:

       利用DFT系数的特性,合并DFT运算中的某些项; 把长序列DFT→短序列DFT,从而减少运算量。


FFT算法分类:    时间抽选法     DIT: Decimation-In-Time

                          频率抽选法      DIF: Decimation-In-Frequency



4、按时间抽选的基2-FFT算法

           1、算法原理

         设输入序列长度为N=(M为正整数,将该序列按时间顺序的奇偶分解为越来越短的子序列,称为基2按时间抽取的FFT算法。也称为Coolkey-Tukey算法。其中基2表示:N=,M为整数.若不满足这个条件,可以人为地加上若干零值(加零补长)使其达到 N=。

            2、算法步骤

     (1)分组,变量置换

            先将x(n)按n的奇偶分为两组,作变量置换:
                                                                   当n=偶数时,令n=2r;
                                                                   当n=奇数时,令n=2r+1;

          得到:


     (2)带入DFT中






         3、算法比较



DIT―FFT算法与直接计算DFT运算量的比较



          4、运算规律及编程思想

1) 原位运算  (亦称同址计算)

         FFT的每级(列)计算都是由N个复数数据(输入)两两构成一个蝶型(共N/2个蝶形)运算而得到另外N个复数数据(输出)。当数据输入到存储器以后,每一组运算的结果,仍然存放在这同一组存储器中直到最后输出。

2)旋转因子的变化规律


如上所述,N点DIT―FFT运算流图中,每级都有N/2个蝶形。每个蝶形都要乘以因子,称其为旋转因子,p称为旋转因子的指数。观察FFT运算流图发现,第L级共有个不同的旋转因子。N==8时的各级旋转因子表示如下:




3)编程思想及流程图


4)码位倒序

    由N=8蝶形图看出:原位计算时,FFT输出的X(k)的次序正好是顺序排列的,即X(0)…X(7),但输入x(n)都不能按自然顺序存入到存储单元中,而是按x(0),x(4),x(2),x(6) ,x(1),x(5),x(3),x(7)的顺序存入存储单元,即为乱序输入,顺序输出。
       这种顺序看起来相当杂乱,然而它是有规律的。即码位倒读规则。以N=8为例:


看出:码位倒读后的顺序刚好是数据送入计算机内的顺序。


分析: 

            对于数N,在其二进制最高位加1,等于加N/2。

           若已知某个反序号为J,为求下一个反序号,可先判J的最高位:
     1)  若为0,则把该位变成1(即加N/2)就得到下
           一个反序号,
     2)  若为1,则需判断次高位:
           ① 若次高位为0,则把最高位变0(相当减去
                N/2)后,再把次高位变1(即加N/4)。
           ② 若次高位为1,则需判断次次高位……



5、算法实现

/************FFT***********/
#include   
#include   
#include   


#define   N   1000
typedef   struct//复数的定义
{
	double   real;//复数的实部
	double   img;//复数的虚部
}complex;


void   fft(); /*快速傅里叶变换*/ 
void   ifft(); /*快速傅里叶逆变换*/ 
void   initW();//快速核变换
void   change();//将x(n)倒置
void   add(complex   ,complex   ,complex   *);   /*复数加法*/   
void   mul(complex   ,complex   ,complex   *);   /*复数乘法*/   
void   sub(complex   ,complex   ,complex   *);   /*复数减法*/   
void   divi(complex   ,complex   ,complex   *);/*复数除法*/   
void   output(); /*输出结果*/

complex   x[N],   *W;   /*输出序列的值*/
int   size_x=0;         /*输入序列的长度,只限2的N次方*/
double   PI;

int   main()
{
	int   i,method;
	
	system("cls");
	PI=atan(1)*4;    /*pi等于4乘以1.0的正切值*/
	printf("Please   input   the   size   of   x:\n");	/*输入序列的长度*/
	scanf("%d",&size_x);

	printf("Please   input   the   data   in   x[N]:(such as:5 6)\n");	/*输入序列对应的值*/
	for(i=0;i0   )   
		{   
			j=j<<1; //左移符号,把相关值的二进制位向左移动,右边空出的全部补0
			j|=(k&1);  //&按位“与”运算符 ;|“按位或”
			k=k>>1;   //“>>”代表右移运算符
		}   
		if(j>i)   
		{   
			temp=x[i];   
			x[i]=x[j];   
			x[j]=temp;   
		}   
	}   
}   


void   output()   /*输出结果*/
{   
	int   i;   
	printf("The   result   are   as   follows\n");   
	for(i=0;i=0.0001)   
			printf("+%.4fj\n",x[i].img);   
		else   if(fabs(x[i].img)<0.0001)   
			printf("\n");   
		else     
			printf("%.4fj\n",x[i].img);   
	}   
}  

 
void   add(complex   a,complex   b,complex   *c) //复数相加  
{   
	c->real=a.real+b.real;   
	c->img=a.img+b.img;   
}   


void   mul(complex   a,complex   b,complex   *c)  //复数相乘 
{   
	c->real=a.real*b.real-a.img*b.img;   
	c->img=a.real*b.img+a.img*b.real;   
}   

void   sub(complex   a,complex   b,complex   *c)   //复数相减 
{   
	c->real=a.real-b.real;   
	c->img=a.img-b.img;   
}  
 
void   divi(complex   a,complex   b,complex   *c)   //复数相除 
{   
	c->real=(   a.real*b.real+a.img*b.img)/(b.real*b.real+b.img*b.img);   
	c->img=(   a.img*b.real-a.real*b.img)/(b.real*b.real+b.img*b.img);   
} 

结果为:


你可能感兴趣的:(图像相关)