一维快速傅里叶变换与反变换
/************************************************************************* * * \函数名称: * FFT_1D() * * \输入参数: * complex<double> * pCTData - 指向时域数据的指针,输入的需要变换的数据 * complex<double> * pCFData - 指向频域数据的指针,输出的经过变换的数据 * nLevel -傅立叶变换蝶形算法的级数,2的幂数, * * \返回值: * 无 * * \说明: * 一维快速傅立叶变换。 * ************************************************************************* */ VOID WINAPI FFT_1D(complex<double> * pCTData, complex<double> * pCFData, int nLevel) { // 循环控制变量 int i; int j; int k; double PI = 3.1415926; // 傅立叶变换点数 int nCount =0 ; // 计算傅立叶变换点数 nCount =(int)pow(2,nLevel) ; // 某一级的长度 int nBtFlyLen; nBtFlyLen = 0 ; // 变换系数的角度 =2 * PI * i / nCount double dAngle; complex<double> *pCW ; // 分配内存,存储傅立叶变化需要的系数表 pCW = new complex<double>[nCount / 2]; // 计算傅立叶变换的系数 for(i = 0; i < nCount / 2; i++) { dAngle = -2 * PI * i / nCount; pCW[i] = complex<double> ( cos(dAngle), sin(dAngle) ); } // 变换需要的工作空间 complex<double> *pCWork1,*pCWork2; // 分配工作空间 pCWork1 = new complex<double>[nCount]; pCWork2 = new complex<double>[nCount]; // 临时变量 complex<double> *pCTmp; // 初始化,写入数据 memcpy(pCWork1, pCTData, sizeof(complex<double>) * nCount); // 临时变量 int nInter; nInter = 0; // 蝶形算法进行快速傅立叶变换 for(k = 0; k < nLevel; k++) { for(j = 0; j < (int)pow(2,k); j++) { //计算长度 nBtFlyLen = (int)pow( 2,(nLevel-k) ); //倒序重排,加权计算 for(i = 0; i < nBtFlyLen/2; i++) { nInter = j * nBtFlyLen; pCWork2[i + nInter] = pCWork1[i + nInter] + pCWork1[i + nInter + nBtFlyLen / 2]; pCWork2[i + nInter + nBtFlyLen / 2] = (pCWork1[i + nInter] - pCWork1[i + nInter + nBtFlyLen / 2]) * pCW[(int)(i * pow(2,k))]; } } // 交换 pCWork1和pCWork2的数据 pCTmp = pCWork1 ; pCWork1 = pCWork2 ; pCWork2 = pCTmp ; } // 重新排序 for(j = 0; j < nCount; j++) { nInter = 0; for(i = 0; i < nLevel; i++) { if ( j&(1<<i) ) { nInter += 1<<(nLevel-i-1); } } pCFData[j]=pCWork1[nInter]; } // 释放内存空间 delete pCW; delete pCWork1; delete pCWork2; pCW = NULL ; pCWork1 = NULL ; pCWork2 = NULL ; } /************************************************************************* * * \函数名称: * IFFT_1D() * * \输入参数: * complex<double> * pCTData - 指向时域数据的指针,输入的需要反变换的数据 * complex<double> * pCFData - 指向频域数据的指针,输出的经过反变换的数据 * nLevel -傅立叶变换蝶形算法的级数,2的幂数, * * \返回值: * 无 * * \说明: * 一维快速傅立叶反变换。 * ************************************************************************ */ VOID WINAPI IFFT_1D(complex<double> * pCFData, complex<double> * pCTData, int nLevel) { // 循环控制变量 int i; // 傅立叶反变换点数 int nCount; // 计算傅立叶变换点数 nCount = (int)pow(2,nLevel) ; // 变换需要的工作空间 complex<double> *pCWork; // 分配工作空间 pCWork = new complex<double>[nCount]; // 将需要反变换的数据写入工作空间pCWork memcpy(pCWork, pCFData, sizeof(complex<double>) * nCount); // 为了利用傅立叶正变换,可以把傅立叶频域的数据取共轭 // 然后直接利用正变换,输出结果就是傅立叶反变换结果的共轭 for(i = 0; i < nCount; i++) { pCWork[i] = complex<double> (pCWork[i].real(), -pCWork[i].imag()); } // 调用快速傅立叶变换实现反变换,结果存储在pCTData中 FFT_1D(pCWork, pCTData, nLevel); // 求时域点的共轭,求得最终结果 // 根据傅立叶变换原理,利用这样的方法求得的结果和实际的时域数据 // 相差一个系数nCount for(i = 0; i < nCount; i++) { pCTData[i] = complex<double> (pCTData[i].real() / nCount, -pCTData[i].imag() / nCount); } // 释放内存 delete pCWork; pCWork = NULL; }二维快速傅里叶变换与反变换
/************************************************************************* * * \函数名称: * FFT_2D() * * \输入参数: * complex<double> * pCTData - 图像数据 * int nWidth - 数据宽度 * int nHeight - 数据高度 * complex<double> * pCFData - 傅立叶变换后的结果 * * \返回值: * 无 * * \说明: * 二维快速傅立叶变换。 * ************************************************************************ */ VOID WINAPI DIBFFT_2D(complex<double> * pCTData, int nWidth, int nHeight, complex<double> * pCFData) { // 循环控制变量 int x; int y; // 临时变量 double dTmpOne; double dTmpTwo; // 进行傅立叶变换的宽度和高度,(2的整数次幂) // 图像的宽度和高度不一定为2的整数次幂 int nTransWidth; int nTransHeight; // 计算进行傅立叶变换的宽度 (2的整数次幂) dTmpOne = log(nWidth)/log(2); dTmpTwo = ceil(dTmpOne) ; dTmpTwo = pow(2,dTmpTwo) ; nTransWidth = (int) dTmpTwo ; // 计算进行傅立叶变换的高度 (2的整数次幂) dTmpOne = log(nHeight)/log(2); dTmpTwo = ceil(dTmpOne) ; dTmpTwo = pow(2,dTmpTwo) ; nTransHeight = (int) dTmpTwo ; // x,y(行列)方向上的迭代次数 int nXLev; int nYLev; // 计算x,y(行列)方向上的迭代次数 nXLev = (int) ( log(nTransWidth)/log(2) + 0.5 ); nYLev = (int) ( log(nTransHeight)/log(2) + 0.5 ); for(y = 0; y < nTransHeight; y++) { // x方向进行快速傅立叶变换 FFT_1D(&pCTData[nTransWidth * y], &pCFData[nTransWidth * y], nXLev); } // pCFData中目前存储了pCTData经过行变换的结果 // 为了直接利用FFT_1D,需要把pCFData的二维数据转置,再一次利用FFT_1D进行 // 傅立叶行变换(实际上相当于对列进行傅立叶变换) for(y = 0; y < nTransHeight; y++) { for(x = 0; x < nTransWidth; x++) { pCTData[nTransHeight * x + y] = pCFData[nTransWidth * y + x]; } } for(x = 0; x < nTransWidth; x++) { // 对x方向进行快速傅立叶变换,实际上相当于对原来的图象数据进行列方向的 // 傅立叶变换 FFT_1D(&pCTData[x * nTransHeight], &pCFData[x * nTransHeight], nYLev); } // pCFData中目前存储了pCTData经过二维傅立叶变换的结果,但是为了方便列方向 // 的傅立叶变换,对其进行了转置,现在把结果转置回来 for(y = 0; y < nTransHeight; y++) { for(x = 0; x < nTransWidth; x++) { pCTData[nTransWidth * y + x] = pCFData[nTransHeight * x + y]; } } memcpy(pCTData, pCFData, sizeof(complex<double>) * nTransHeight * nTransWidth ); } /************************************************************************* * * \函数名称: * IFFT_2D() * * \输入参数: * complex<double> * pCFData - 频域数据 * complex<double> * pCTData - 时域数据 * int nWidth - 图像数据宽度 * int nHeight - 图像数据高度 * * \返回值: * 无 * * \说明: * 二维傅立叶反变换。 * ************************************************************************ */ VOID WINAPI IFFT_2D(complex<double> * pCFData, complex<double> * pCTData, int nWidth, int nHeight) { // 循环控制变量 int x; int y; // 临时变量 double dTmpOne; double dTmpTwo; // 进行傅立叶变换的宽度和高度,(2的整数次幂) // 图像的宽度和高度不一定为2的整数次幂 int nTransWidth; int nTransHeight; // 计算进行傅立叶变换的宽度 (2的整数次幂) dTmpOne = log(nWidth)/log(2); dTmpTwo = ceil(dTmpOne) ; dTmpTwo = pow(2,dTmpTwo) ; nTransWidth = (int) dTmpTwo ; // 计算进行傅立叶变换的高度 (2的整数次幂) dTmpOne = log(nHeight)/log(2); dTmpTwo = ceil(dTmpOne) ; dTmpTwo = pow(2,dTmpTwo) ; nTransHeight = (int) dTmpTwo ; // 分配工作需要的内存空间 complex<double> *pCWork= new complex<double>[nTransWidth * nTransHeight]; //临时变量 complex<double> *pCTmp ; // 为了利用傅立叶正变换,可以把傅立叶频域的数据取共轭 // 然后直接利用正变换,输出结果就是傅立叶反变换结果的共轭 for(y = 0; y < nTransHeight; y++) { for(x = 0; x < nTransWidth; x++) { pCTmp = &pCFData[nTransWidth * y + x] ; pCWork[nTransWidth * y + x] = complex<double>( pCTmp->real() , -pCTmp->imag() ); } } // 调用傅立叶正变换 ::DIBFFT_2D(pCWork, nWidth, nHeight, pCTData) ; // 求时域点的共轭,求得最终结果 // 根据傅立叶变换原理,利用这样的方法求得的结果和实际的时域数据 // 相差一个系数 for(y = 0; y < nTransHeight; y++) { for(x = 0; x < nTransWidth; x++) { pCTmp = &pCTData[nTransWidth * y + x] ; pCTData[nTransWidth * y + x] = complex<double>( pCTmp->real()/(nTransWidth*nTransHeight), -pCTmp->imag()/(nTransWidth*nTransHeight) ); } } delete pCWork ; pCWork = NULL ; }