📄 fft.cpp
字号:
}
}
delete []array;
//再横向一维快速傅立叶变换
for(v=0;v<height;v++){
FFT1D(m_pFFTBuf+v*width, width);
}
//将频谱图以图像形式存入imgBufOut
float t;
int i0,j0;
for(i=0;i<height;i++){
//i0 = i;
//j0 = j;
for(j=0;j<width;j++){
if(i<height/2)
i0=i+height/2;
else
i0=i-height/2;
if(j<width/2)
j0=j+width/2;
else
j0=j-width/2;
t=sqrt(m_pFFTBuf[i0*width+j0].real*m_pFFTBuf[i0*width+j0].real
+m_pFFTBuf[i0*width+j0].imag*m_pFFTBuf[i0*width+j0].imag);
t=t/500;
if(t>255)
imgBufOut[i*width+j]=255;
else
imgBufOut[i*width+j]=t;
}
}
}
/***********************************************************************
* 函数名称:
* IFFT1D()
*
*函数参数:
* ComplexNumber *arrayBuf -复数结构体类型数组
* int n -数组arrayBuf的长度,必须为2的幂次方
*
*返回值:
* 无
*
*说明:对复数结构体数组arrayBuf进行一维快速傅立叶反变换,变换后的结果仍
* 存回arrayBuf中
***********************************************************************/
void Transform_FFT::IFFT1D(ComplexNumber *arrayBuf, int n)
{
//变量
int i;
//对数组arrayBuf求共轭
for(i=0;i<n;i++)
arrayBuf[i].imag=-arrayBuf[i].imag;
//一维快速傅立叶变换
FFT1D(arrayBuf, n);
//时域数据求共轭,并除以N
for(i=0;i<n;i++){
arrayBuf[i].real=arrayBuf[i].real/n;
arrayBuf[i].imag=-arrayBuf[i].imag/n;
}
}
/***********************************************************************
* 函数名称:
* ImgIFFT2D()
*
*函数参数:
* unsigned char* imgBufOut -输出图像数据指针
* int width -图像宽
* int height -图像高
*
*返回值:
* 无
*
*说明:对傅立叶变换缓冲区m_pFFTBuf里的数据,进行两个一维快速傅立叶反变换,
* 变换后的频谱即是原图像的恢复数据,将恢复数据存入imgBufOut,此处要求
* 图像宽和高均为2的幂次方
***********************************************************************/
void Transform_FFT::ImgIFFT2D(unsigned char* imgBufOut, int width, int height)
{
//若傅立叶变换缓冲区为空,则失败返回
if(!m_pFFTBuf)
return;
//变量
int i, u, v;
//先纵向傅立叶反变换
ComplexNumber *array=new ComplexNumber[height];
for(u=0;u<width;u++){
for(v=0;v<height;v++){
array[v].real=m_pFFTBuf[v*width+u].real;
array[v].imag=m_pFFTBuf[v*width+u].imag;
}
IFFT1D(array, height);
for(v=0;v<height;v++){
m_pFFTBuf[v*width+u].real=array[v].real;
m_pFFTBuf[v*width+u].imag=array[v].imag;
}
}
delete []array;
//再横向傅立叶反变换
for(v=0;v<height;v++){
IFFT1D(m_pFFTBuf+v*width, width);
}
//求m_pFFTBuf的幅度谱,恢复图像存入imgBufOut
float t;
for(i=0;i<width*height;i++){
t=sqrt(m_pFFTBuf[i].real*m_pFFTBuf[i].real
+m_pFFTBuf[i].imag*m_pFFTBuf[i].imag);
if(t>255)
imgBufOut[i]=255;
else imgBufOut[i]=t;
}
}
/***********************************************************************
* 函数名称:
* Fourier()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:对输入图像进行快速傅立叶变换,要求输入图像的宽和高必须是2的幂次方
***********************************************************************/
void Transform_FFT::Fourier()
{
//输出图像的大小与输入图像相同
m_imgWidthOut=m_imgWidth;
m_imgHeightOut=m_imgHeight;
//申请输出图像缓冲区,并初始化为0
m_pImgDataOut=new unsigned char[m_imgWidthOut*m_imgHeightOut];
memset(m_pImgDataOut, 0, m_imgWidthOut*m_imgHeightOut);
//申请傅立叶缓冲区,并初始化为0
m_pFFTBuf=new ComplexNumber[m_imgWidthOut*m_imgHeightOut];
memset(m_pFFTBuf, 0, sizeof(ComplexNumber)*m_imgWidthOut*m_imgHeightOut);
//输入图像数据进行二维傅立叶变换
ImgFFT2D(m_pImgData, m_imgWidthOut, m_imgHeightOut, m_pImgDataOut);
}
/***********************************************************************
* 函数名称:
* IFourier()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:输入图像的快速傅立叶反变换,与ImgFFT()成对调用
***********************************************************************/
void Transform_FFT::IFourier()
{
//图像的二维傅立叶反变换,变换结果即是恢复的原图像,存入m_pImgDataOut
ImgIFFT2D(m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
}
/***********************************************************************
* 函数名称:
* FourierEx()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:若图像长和宽是2的幂次方,则直接调用ImgFFT()进行傅立叶变换,否则,
* 对输入图像的长和宽进行2的幂次的扩展,对扩展后的图像数据进行快速傅
* 立叶变换,因此该函数适合于任意大小图像的傅立叶变换
***********************************************************************/
void Transform_FFT::FourierEx()
{
//判断输入图像长和宽是否是2的幂次方,若是isPowerOf2置1,否则isPowerOf2置0
int isPowerOf2=1;
int i=1;
while(i<m_imgWidth)
i=i*2;
if(i!=m_imgWidth)//宽不是2的幂次方
isPowerOf2=0;
i=1;
while(i<m_imgHeight)
i=i*2;
if(i!=m_imgHeight)//高不是2的幂次方
isPowerOf2=0;
//输入图像长和宽若是2的幂次方,则不需要扩展,直接调用ImgFFT()函数即可
if(isPowerOf2) {
Fourier();
}
else{
//输入图像长或宽不是2的幂次方,则将图像补零扩展
//计算应扩展缓冲区的大小
i=1;
while(i<m_imgWidth)
i=i*2;
m_imgWidthOut=i;
i=1;
while(i<m_imgHeight)
i=i*2;
m_imgHeightOut=i;
//申请扩展缓冲区m_pImgExpandBuf
m_pImgExpandBuf=new unsigned char[m_imgWidthOut*m_imgHeightOut];
//m_pImgExpandBuf缓冲区置0
memset(m_pImgExpandBuf, 0, m_imgWidthOut*m_imgHeightOut);
//循环变量,图像的坐标
int i,j;
//输入图像每行像素字节数
int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;
//输入图像数据拷贝到m_pImgExpandBuf的左下角部分,其余为0
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
*(m_pImgExpandBuf+i*m_imgWidthOut+j)=*(m_pImgData+i*lineByte+j);
}
}
//申请输出图像缓冲区,并初始化为0
m_pImgDataOut=new unsigned char[m_imgWidthOut*m_imgHeightOut];
memset(m_pImgDataOut, 0, m_imgWidthOut*m_imgHeightOut);
//申请傅立叶缓冲区,并初始化为0
m_pFFTBuf=new ComplexNumber[m_imgWidthOut*m_imgHeightOut];
memset(m_pFFTBuf, 0, sizeof(ComplexNumber)*m_imgWidthOut*m_imgHeightOut);
//扩展后的数据进行二维傅立叶变换
ImgFFT2D(m_pImgExpandBuf, m_imgWidthOut, m_imgHeightOut, m_pImgDataOut);
//图像被扩展的标志变量置真
m_isExpanded=TRUE;
}
}
/***********************************************************************
* 函数名称:
* IFourierEx()
*
*函数参数:
* 无
*
*返回值:
* 无
*
*说明:输入图像扩展后的快速傅立叶反变换,与ImgFFTEx()成对调用
***********************************************************************/
void Transform_FFT::IFourierEx()
{
//图像的二维傅立叶反变换,变换结果存入m_pImgDataOut
ImgIFFT2D(m_pImgDataOut, m_imgWidthOut, m_imgHeightOut);
//若m_isExpanded为真,则说明原图像是经过扩展补零的,m_pImgDataOut内的图
//像数据是扩展后的恢复数据,此时应将扩展部分删除掉
if(m_isExpanded==TRUE){
//循环变量,图像的坐标
int i,j;
//输入图像每行像素字节数
int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4;
//申请输入图像大小的缓冲区,将m_pImgDataOut中真正的图像数据拷贝出来
unsigned char *pBuf=new unsigned char[lineByte*m_imgHeight];
for(i=0;i<m_imgHeight;i++){
for(j=0;j<m_imgWidth;j++){
*(pBuf+i*lineByte+j)=*(m_pImgDataOut+i*m_imgWidthOut+j);
}
}
//释放扩展后的图像恢复数据m_pImgDataOut
delete []m_pImgDataOut;
//m_pImgDataOut指向真正图像的恢复数据
m_pImgDataOut=pBuf;
//输出图像的宽高
m_imgWidthOut=m_imgWidth;
m_imgHeightOut=m_imgHeight;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -