?? fouriertransforms.cpp
字號:
* complex<double> * pCFData - 指向頻域值的指針
* complex<double> * pCTData - 指向時域值的指針
* nLevel -付立葉變換蝶形算法的級數(shù),2的冪數(shù)
*
* 返回值:
* 無。
*
* 說明:
* 該函數(shù)用來實現(xiàn)快速付立葉反變換。
*
************************************************************************/
LLVPRO_API void IFFT_1D(complex<double> * pCFData, complex<double> * pCTData, int nLevel)
{
// 付立葉變換點數(shù)
long lcount;
// 循環(huán)變量
int i;
complex<double> *pCWork;
// 計算付立葉變換點數(shù)
lcount = 1 << nLevel;
// 分配運算所需存儲器
pCWork = new complex<double>[lcount];
// 將頻域點寫入pCWork
memcpy(pCWork, pCFData, sizeof(complex<double>) * lcount);
// 為了利用付立葉正變換,可以把付立葉頻域的數(shù)據(jù)取共軛
// 然后直接利用正變換,輸出結(jié)果就是付立葉反變換結(jié)果的共軛
for(i = 0; i < lcount; i++)
{
pCWork[i] = complex<double> (pCWork[i].real(), -pCWork[i].imag());
}
// 調(diào)用快速付立葉變換實現(xiàn)反變換,結(jié)果存儲在pCTData中
FFT_1D_Opti(pCWork, pCTData, nLevel);
// 求時域點的共軛,求得最重結(jié)果
// 根據(jù)付立葉變換原理,利用這樣的方法求的結(jié)果和實際的時域數(shù)據(jù)
// 相差一個系數(shù)nCount
for(i = 0; i < lcount; i++)
{
pCTData[i] = complex<double> (pCTData[i].real() / lcount, -pCTData[i].imag() / lcount);
}
// 釋放內(nèi)存
if( pCWork!=NULL )
{
delete []pCWork;
pCWork = NULL;
}
}
/*************************************************************************
*
* \函數(shù)名稱:
* FFT_2D()
*
* \輸入?yún)?shù):
* complex<double> * pCTData - 圖像數(shù)據(jù)
* complex<double> * pCFData - 傅立葉變換后的結(jié)果
* long lTransWidth - 變換數(shù)據(jù)寬度
* long lTransHeight - 變換數(shù)據(jù)高度
*
* \返回值:
* TRUE 變換成功
* FALSE 變換失敗
*
* \說明:
* 二維傅立葉變換。
* 不負責(zé)pCTData的補零操作
************************************************************************/
LLVPRO_API BOOL FFT_2D(complex<double> * pCTData, complex<double> * pCFData,long lTransWidth, long lTransHeight)
{
if(pCTData==NULL||pCFData==NULL||lTransWidth<=0||lTransHeight<=0)
{
return FALSE;
}
// 循環(huán)控制變量
int x;
int y;
// x,y(行列)方向上的迭代次數(shù)
int nXLev;
int nYLev;
// 計算x,y(行列)方向上的迭代次數(shù)
nXLev = (int) ( log(lTransWidth)/log(2) ) ;
nYLev = (int) ( log(lTransHeight)/log(2)) ;
if(((1 << nXLev)!=lTransWidth)||((1 << nYLev)!=lTransHeight))
{
return FALSE;
}
for(y = 0; y < lTransHeight; y++)
{
// x方向進行快速傅立葉變換
// FFT_1D(&pCTData[lTransWidth * y], &pCFData[lTransWidth * y], nXLev);
FFT_1D_Opti(&pCTData[lTransWidth * y], &pCFData[lTransWidth * y], nXLev);
}
// pCFData中目前存儲了pCTData經(jīng)過行變換的結(jié)果
// 為了直接利用FFT_1D,需要把pCFData的二維數(shù)據(jù)轉(zhuǎn)置,再一次利用FFT_1D進行
// 傅立葉行變換(實際上相當于對列進行傅立葉變換)
for(y = 0; y < lTransHeight; y++)
{
for(x = 0; x < lTransWidth; x++)
{
pCTData[lTransHeight * x + y] = pCFData[lTransWidth * y + x];
}
}
for(x = 0; x < lTransWidth; x++)
{
// 對x方向進行快速傅立葉變換,實際上相當于對原來的圖象數(shù)據(jù)進行列方向的
// 傅立葉變換
// FFT_1D(&pCTData[lTransHeight * x], &pCFData[lTransHeight * x], nYLev);
FFT_1D_Opti(&pCTData[x * lTransHeight], &pCFData[x * lTransHeight], nYLev);
}
// pCFData中目前存儲了pCTData經(jīng)過二維傅立葉變換的結(jié)果,但是為了方便列方向
// 的傅立葉變換,對其進行了轉(zhuǎn)置,現(xiàn)在把結(jié)果轉(zhuǎn)置回來
for(y = 0; y < lTransHeight; y++)
{
for(x = 0; x < lTransWidth; x++)
{
pCTData[lTransWidth * y + x] = pCFData[lTransHeight * x + y];
}
}
memcpy(pCFData,pCTData, sizeof(complex<double>) * lTransHeight * lTransWidth );
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* IFFT_2D()
*
* \輸入?yún)?shù):
* complex<double> * pCFData - 頻域數(shù)據(jù)
* complex<double> * pCTData - 時域數(shù)據(jù)
* long lTransWidth - 變換數(shù)據(jù)寬度
* long lTransHeight - 變換數(shù)據(jù)高度
*
* \返回值:
* TRUE 變換成功
* FALSE 變換失敗
*
* \說明:
* 二維傅立葉反變換。
*
*************************************************************************/
LLVPRO_API BOOL IFFT_2D(complex<double> * pCFData, complex<double> * pCTData, long lTransWidth, long lTransHeight)
{
if(pCTData==NULL||pCFData==NULL||lTransWidth<=0||lTransHeight<=0)
{
return FALSE;
}
// x,y(行列)方向上的迭代次數(shù)
int nXLev;
int nYLev;
// 計算x,y(行列)方向上的迭代次數(shù)
nXLev = (int) ( log(lTransWidth)/log(2) );
nYLev = (int) ( log(lTransHeight)/log(2) );
if(((1 << nXLev)!=lTransWidth)||((1 << nYLev)!=lTransHeight))
{
return FALSE;
}
// 循環(huán)控制變量
int x;
int y;
// 分配工作需要的內(nèi)存空間
complex<double> *pCWork= new complex<double>[lTransWidth * lTransHeight];
//臨時變量
complex<double> *pCTmp ;
// 為了利用傅立葉正變換,可以把傅立葉頻域的數(shù)據(jù)取共軛
// 然后直接利用正變換,輸出結(jié)果就是傅立葉反變換結(jié)果的共軛
for(y = 0; y < lTransHeight; y++)
{
for(x = 0; x < lTransWidth; x++)
{
pCTmp = &pCFData[lTransWidth * y + x] ;
pCWork[lTransWidth * y + x] = complex<double>( pCTmp->real() , -pCTmp->imag() );
}
}
// 調(diào)用傅立葉正變換
FFT_2D(pCWork, pCTData,lTransWidth, lTransHeight) ;
// 求時域點的共軛,求得最終結(jié)果
// 根據(jù)傅立葉變換原理,利用這樣的方法求得的結(jié)果和實際的時域數(shù)據(jù)
// 相差一個系數(shù)
for(y = 0; y < lTransHeight; y++)
{
for(x = 0; x < lTransWidth; x++)
{
pCTmp = &pCTData[lTransWidth * y + x] ;
pCTData[lTransWidth * y + x] = complex<double>( pCTmp->real()/(lTransWidth*lTransHeight),
-pCTmp->imag()/(lTransWidth*lTransHeight) );
}
}
delete []pCWork ;
pCWork = NULL ;
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* DIBFFT_2D()
*
* \輸入?yún)?shù):
* LPBYTE pbyImage - 圖像數(shù)據(jù)
* long lWidth - 數(shù)據(jù)寬度
* long lHeight - 數(shù)據(jù)高度
* long lTransWidth - 變換寬度
* long lTransHeight - 變換高度
* complex<double> * pCFData - 頻域數(shù)據(jù),中心變換后的數(shù)據(jù)
* \返回值:
* TRUE 變換成功
* FALSE 變換失敗
*
* \說明:
* 圖像二維傅立葉變換。
* 若lWidth!=lTransWidth||lHeight!=lTransHeight,對時域數(shù)據(jù)進行補零操作
* pCFData 數(shù)據(jù)經(jīng)過中心變換
*************************************************************************/
LLVPRO_API BOOL DIBFFT_2D(LPBYTE pbyImage,long lWidth,long lHeight,long &lTransWidth,long &lTransHeight,complex<double>* &pCFData)
{
// 空域變換尺寸必須不小于圖像尺寸
if(pbyImage == NULL||lWidth <= 0||lHeight <0 )
{
return FALSE;
}
int x,y;
// 臨時變量
double dTmpOne;
double dTmpTwo;
// 計算進行傅立葉變換的點數(shù) (2的整數(shù)次冪)
dTmpOne = log(lWidth)/log(2) ;
dTmpTwo = ceil(dTmpOne) ;
dTmpTwo = pow(2,dTmpTwo) ;
lTransWidth = (long) dTmpTwo ;
// 計算進行傅立葉變換的點數(shù) (2的整數(shù)次冪)
dTmpOne = log(lHeight)/log(2) ;
dTmpTwo = ceil(dTmpOne) ;
dTmpTwo = pow(2,dTmpTwo) ;
lTransHeight = (long) dTmpTwo ;
if(pCFData != NULL)
{
xfree(pCFData);
pCFData = NULL;
}
pCFData = (complex<double>*)xmalloc(lTransWidth * lTransHeight*sizeof(complex<double>));
if(pCFData == NULL)
{
return FALSE;
}
// 指向時域數(shù)據(jù)的指針
complex<double>* pCTData = new complex<double>[lTransWidth * lTransHeight];
// 初始化
// 圖象數(shù)據(jù)的寬和高不一定是2的整數(shù)次冪,所以pCTData
// 有一部分數(shù)據(jù)需要補0
if(lHeight!=lTransHeight)
{
memset(pCTData+lHeight,0,sizeof(complex<double>)*lTransWidth*(lTransHeight-lHeight));
}
if(lWidth != lTransWidth)
{
for(y=0; y< lHeight ; y++)
{
memset(pCTData+y*lTransWidth+lWidth,0,sizeof(complex<double>)*(lTransWidth-lWidth));
}
}
// 把圖象數(shù)據(jù)傳給pCTData,并進行中心變換
for(y=0; y<lHeight; y++)
{
for(x=0; x<lWidth; x++)
{
BYTE unchValue = pbyImage[y*lWidth +x] ;
if((x+y)%2==0)
{
pCTData[y*lTransWidth + x]=complex<double>(unchValue,0);
}
else
{
pCTData[y*lTransWidth + x]=complex<double>(-unchValue,0);
}
}
}
// 傅立葉正變換
if(!FFT_2D(pCTData,pCFData,lTransWidth, lTransHeight) )
{
return FALSE;
}
if(pCTData!=NULL)
{
delete []pCTData;
pCTData = NULL;
}
return TRUE;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -