怎样做二维付利叶变换? 我在做雷达成像是要用到二维付利叶变换,未曾学过,不知该如何入手。请大家指点一下输入信号为二维矩阵,是雷达在不同角度的回波信号,第一维是某角度的回波信号,第二维是转动角度值,如何对该矩阵做付利叶变换 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 void FreqChange(complex<double> * FD,long lWidth,long lHeight){//由于经过FFT变换时候,低频不在中心,变换 long i,j; complex<double> temp;//移位临时变量 for(i = 0; i < lHeight/2; i++) { // 列 for(j = 0; j < lWidth; j++) { temp = FD[ (lHeight-1-i)*lWidth + j]; FD[ (lHeight-1-i)*lWidth + j] = FD[ (lHeight/2-1-i)*lWidth + (lWidth/2+j)%(lWidth)]; FD[ (lHeight/2-1-i)*lWidth + (lWidth/2+j)%(lWidth)] = temp; } }}/************************************************************************* * * 函数名称: * FFT() * * 参数: * complex<double> * TD - 指向时域数组的指针 * complex<double> * FD - 指向频域数组的指针 * r -2的幂数,即迭代次数 * * 返回值: * 无。 * * 说明: * 该函数用来实现快速付立叶变换。 * ************************************************************************/void FFT(complex<double> * TD, complex<double> * FD, int r){ // 付立叶变换点数 long count; // 循环变量 int i,j,k; // 中间变量 int bfsize,p; // 角度 double angle; complex<double> *W,*X1,*X2,*X; // 计算付立叶变换点数 count = 1 << r; // 分配运算所需存储器 W = new complex<double>[count / 2]; X1 = new complex<double>[count]; X2 = new complex<double>[count]; // 计算加权系数 for(i = 0; i < count / 2; i++) { angle = -i * PI * 2 / count; W[i] = complex<double> (cos(angle), sin(angle)); } // 将时域点写入X1 memcpy(X1, TD, sizeof(complex<double>) * count); // 采用蝶形算法进行快速付立叶变换 for(k = 0; k < r; k++) { for(j = 0; j < 1 << k; j++) { bfsize = 1 << (r-k); for(i = 0; i < bfsize / 2; i++) { p = j * bfsize; X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2]; X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) * W[i * (1<<k)]; } } X = X1; X1 = X2; X2 = X; } // 重新排序 for(j = 0; j < count; j++) { p = 0; for(i = 0; i < r; i++) { if (j&(1<<i)) { p+=1<<(r-i-1); } } FD[j]=X1[p]; } // 释放内存 delete W; delete X1; delete X2;}/************************************************************************* * * 函数名称: * IFFT() * * 参数: * complex<double> * FD - 指向频域值的指针 * complex<double> * TD - 指向时域值的指针 * r -2的幂数 * * 返回值: * 无。 * * 说明: * 该函数用来实现快速付立叶反变换。 * ************************************************************************/void IFFT(complex<double> * FD, complex<double> * TD, int r){ // 付立叶变换点数 long count; // 循环变量 int i; complex<double> *X; // 计算付立叶变换点数 count = 1 << r; // 分配运算所需存储器 X = new complex<double>[count]; // 将频域点写入X memcpy(X, FD, sizeof(complex<double>) * count); // 求共轭 for(i = 0; i < count; i++) { X[i] = complex<double> (X[i].real(), -X[i].imag()); } // 调用快速付立叶变换 FFT(X, TD, r); // 求时域点的共轭 for(i = 0; i < count; i++) { TD[i] = complex<double> (TD[i].real() / count, -TD[i].imag() / count); } // 释放内存 delete X;}/************************************************************************* * * 函数名称: * DCT() * * 参数: * double * f - 指向时域值的指针 * double * F - 指向频域值的指针 * r -2的幂数 * * 返回值: * 无。 * * 说明: * 该函数用来实现快速离散余弦变换。该函数利用2N点的快速付立叶变换 * 来实现离散余弦变换。 * ************************************************************************/void DCT(double *f, double *F, int r){ // 离散余弦变换点数 long count; // 循环变量 int i; // 中间变量 double dTemp; complex<double> *X; // 计算离散余弦变换点数 count = 1<<r; // 分配内存 X = new complex<double>[count*2]; // 赋初值为0 memset(X, 0, sizeof(complex<double>) * count * 2); // 将时域点写入数组X for(i=0;i<count;i++) { X[i] = complex<double> (f[i], 0); } // 调用快速付立叶变换 FFT(X,X,r+1); // 调整系数 dTemp = 1/sqrt(count); // 求F[0] F[0] = X[0].real() * dTemp; dTemp *= sqrt(2); // 求F[u] for(i = 1; i < count; i++) { F[i]=(X[i].real() * cos(i*PI/(count*2)) + X[i].imag() * sin(i*PI/(count*2))) * dTemp; } // 释放内存 delete X;}/************************************************************************* * * 函数名称: * DIBIFFT() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * long lWidth - 源图像宽度(象素数) * long lHeight - 源图像高度(象素数) * complex<double>*FD - 频域图象 * complex<double>*TD - 时域图象 * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来对经过FFT变换的图象进行反变换 * ************************************************************************/bool DIBIFFT(BYTE * lpDIBBits,long lWidth,long lHeight, complex<double>*FD,complex<double>*TD){ // 指向源图像的指针 unsigned char* lpSrc; // 中间变量 double dTemp; // 循环变量 long i; long j; // 进行付立叶变换的宽度和高度(2的整数次方) long w; long h; double dMin,dMax; long lCount=0; int wp; int hp; // 图像每行的字节数 long lLineBytes; // 赋初值 w = 1; h = 1; wp = 0; hp = 0; // 计算进行付立叶变换的宽度和高度(2的整数次方) while(w * 2 <= lWidth) { w *= 2; wp++; } while(h * 2 <= lHeight) { h *= 2; hp++; } // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(w * 8); FreqChange(FD,w,h); for(i = 0; i < h; i++) { // 对y方向进行快速反付立叶变换 IFFT(&FD[w * i], &TD[w * i], wp); } // 保存变换结果 for(i = 0; i < h; i++) { for(j = 0; j < w; j++) { FD[ j*h+i ] = TD[ i*w+j ]; } } for(i = 0; i < w; i++) { // 对x方向进行快速反付立叶变换 IFFT(&FD[i * h], &TD[i * h], hp); } /*******************倒序*********************/ for(i = 0; i < h; i++) { for(j = 0; j < w; j++) { FD[(h-1-i)*w+j] =TD[ i+h*j ]; } } for(i = 0; i < h; i++) { for(j = 0; j < w; j++) { TD[ i*w+j ] = FD[ i*w+j ]; } }/******************倒序*************************/ dMin = dMax = TD[0].real(); //应该显示实部 for( i=0;i<w*h;i++ ) { if( dMin>TD[i].real() ) dMin = TD[i].real(); if( dMax<TD[i].real() ) dMax = TD[i].real(); } lCount = long (dMax - dMin); // 行 for(i = 0; i < h; i++) { // 列 for(j = 0; j < w; j++) { //dTemp = (TD[(h-1-i)*w+j].real()-dMin)/lCount*255.0; //dTemp = TD[(h-1-i)*w+j].real(); // 判断是否超过255 dTemp = abs(TD[(h-1-i)*w+j].real()); if (dTemp > 255) { // 对于超过的,直接设置为255 dTemp = 255; } // 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个象素的指针 // 此处不直接取i和j,是为了将变换后的原点移到中心 //lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; lpSrc = (unsigned char*)lpDIBBits + lLineBytes * ( h-1-i)+j; // (h - 1 - (i<h/2 ? i+h/2 : i-h/2)) // + (j<w/2 ? j+w/2 : j-w/2); // 更新源图像 * (lpSrc) = (BYTE)(dTemp); } } // 返回 return TRUE;} /*************************************************************************** 函数名称:* DIBFFT()** 参数:* LPSTR lpDIBBits - 指向源DIB图像指针* long lWidth - 源图像宽度(象素数)* long lHeight - 源图像高度(象素数)* complex<double>*FD - 频域图象* complex<double>*TD - 时域图象* 返回值:* BOOL - 成功返回TRUE,否则返回FALSE。** 说明:* 该函数用来对时域图象进行FFT变换*************************************************************************/bool DIBFFT(BYTE * lpDIBBits,long lWidth,long lHeight, complex<double>*TD,complex<double>*FD){ // 指向源图像的指针 unsigned char* lpSrc; // 中间变量 double dTemp; // 循环变量 long i; long j; // 进行付立叶变换的宽度和高度(2的整数次方) long w; long h; int wp; int hp; // 图像每行的字节数 long lLineBytes; // 赋初值 w = 1; h = 1; wp = 0; hp = 0; // 计算进行付立叶变换的宽度和高度(2的整数次方) while(w * 2 <= lWidth) { w *= 2; wp++; } while(h * 2 <= lHeight) { h *= 2; hp++; } // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(w * 8); // 行 for(i = 0; i < h; i++) { // 列 for(j = 0; j < w; j++) { // 指向DIB第i行,第j个象素的指针 lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; // 给时域赋值 TD[ i*w+j ] = complex<double>(*(lpSrc), 0); } } for(i = 0; i < h; i++) { // 对y方向进行快速付立叶变换 FFT(&TD[w * i], &FD[w * i], wp); } // 保存变换结果 for(i = 0; i < h; i++) { for(j = 0; j < w; j++) { TD[i + h * j] = FD[ i*w+j ]; } } for(i = 0; i < w; i++) { // 对x方向进行快速付立叶变换 FFT(&TD[i * h], &FD[i * h], hp); }/*******************倒序**********************/ for(i = 0; i < h; i++) { for(j = 0; j < w; j++) { TD[i*w+j] = FD[ i+h*j ]; } } for(i = 0; i < h; i++) { for(j = 0; j < w; j++) { FD[ i*w+j ] = TD[ i*w+j ]; } }/*******************倒序*************************/ FreqChange(FD,w,h); // 行 for(i = 0; i < h; i++) { // 列 for(j = 0; j < w; j++) { // 计算频谱 dTemp = abs( FD[ (h-1-i)*w+j ] ) / 100; // 判断是否超过255 if (dTemp > 255) { // 对于超过的,直接设置为255 dTemp = 255; } // 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个象素的指针 // 此处不直接取i和j,是为了将变换后的原点移到中心 //lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; lpSrc = (unsigned char*)lpDIBBits + lLineBytes * ( h-1-i)+j; // (h - 1 - (i<h/2 ? i+h/2 : i-h/2)) // + (j<w/2 ? j+w/2 : j-w/2); // 更新源图像 * (lpSrc) = (BYTE)(dTemp); } } // 返回 return TRUE;}这是我根据VC图象处理这本书改的,包括了2维反FFT,没错的! matlab里有fft的函数可直接使用 无法解析的外部符号 _IID_IHTMLDocument3 再问个关于radio控件的问题,怎样得到一组radio控件的个数? javascript与activex交互问题 VC编码格式 请问对于多Frame的页面如何得到某一坐标点上是哪一个Frame? 如何向自己编写的IE工具条上添加按钮、文本框之类的控件呢? 光标如何下移? DCOM配置的问题 经理要一个算法,我怎么也搞不定,请高手帮忙? 请教微软专家,关于.NET和COM的关系 特别着急的问题,关于应用程序进行加密,是不是应当在用户安装的时候进行啊,请各位高手指点 问一个似易而难的问题~~~~~~~
void FreqChange(complex<double> * FD,long lWidth,long lHeight)
{//由于经过FFT变换时候,低频不在中心,变换 long i,j;
complex<double> temp;//移位临时变量
for(i = 0; i < lHeight/2; i++)
{
// 列
for(j = 0; j < lWidth; j++)
{
temp = FD[ (lHeight-1-i)*lWidth + j]; FD[ (lHeight-1-i)*lWidth + j]
= FD[ (lHeight/2-1-i)*lWidth + (lWidth/2+j)%(lWidth)];
FD[ (lHeight/2-1-i)*lWidth + (lWidth/2+j)%(lWidth)]
= temp;
}
}}
/*************************************************************************
*
* 函数名称:
* FFT()
*
* 参数:
* complex<double> * TD - 指向时域数组的指针
* complex<double> * FD - 指向频域数组的指针
* r -2的幂数,即迭代次数
*
* 返回值:
* 无。
*
* 说明:
* 该函数用来实现快速付立叶变换。
*
************************************************************************/void FFT(complex<double> * TD, complex<double> * FD, int r)
{
// 付立叶变换点数
long count;
// 循环变量
int i,j,k;
// 中间变量
int bfsize,p;
// 角度
double angle;
complex<double> *W,*X1,*X2,*X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
W = new complex<double>[count / 2];
X1 = new complex<double>[count];
X2 = new complex<double>[count];
// 计算加权系数
for(i = 0; i < count / 2; i++)
{
angle = -i * PI * 2 / count;
W[i] = complex<double> (cos(angle), sin(angle));
}
// 将时域点写入X1
memcpy(X1, TD, sizeof(complex<double>) * count);
// 采用蝶形算法进行快速付立叶变换
for(k = 0; k < r; k++)
{
for(j = 0; j < 1 << k; j++)
{
bfsize = 1 << (r-k);
for(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p] = X1[i + p] + X1[i + p + bfsize / 2];
X2[i + p + bfsize / 2] = (X1[i + p] - X1[i + p + bfsize / 2]) * W[i * (1<<k)];
}
}
X = X1;
X1 = X2;
X2 = X;
}
// 重新排序
for(j = 0; j < count; j++)
{
p = 0;
for(i = 0; i < r; i++)
{
if (j&(1<<i))
{
p+=1<<(r-i-1);
}
}
FD[j]=X1[p];
}
// 释放内存
delete W;
delete X1;
delete X2;
}/*************************************************************************
*
* 函数名称:
* IFFT()
*
* 参数:
* complex<double> * FD - 指向频域值的指针
* complex<double> * TD - 指向时域值的指针
* r -2的幂数
*
* 返回值:
* 无。
*
* 说明:
* 该函数用来实现快速付立叶反变换。
*
************************************************************************/void IFFT(complex<double> * FD, complex<double> * TD, int r)
{
// 付立叶变换点数
long count;
// 循环变量
int i;
complex<double> *X;
// 计算付立叶变换点数
count = 1 << r;
// 分配运算所需存储器
X = new complex<double>[count];
// 将频域点写入X
memcpy(X, FD, sizeof(complex<double>) * count);
// 求共轭
for(i = 0; i < count; i++)
{
X[i] = complex<double> (X[i].real(), -X[i].imag());
}
// 调用快速付立叶变换
FFT(X, TD, r);
// 求时域点的共轭
for(i = 0; i < count; i++)
{
TD[i] = complex<double> (TD[i].real() / count, -TD[i].imag() / count);
}
// 释放内存
delete X;
}/*************************************************************************
*
* 函数名称:
* DCT()
*
* 参数:
* double * f - 指向时域值的指针
* double * F - 指向频域值的指针
* r -2的幂数
*
* 返回值:
* 无。
*
* 说明:
* 该函数用来实现快速离散余弦变换。该函数利用2N点的快速付立叶变换
* 来实现离散余弦变换。
*
************************************************************************/
void DCT(double *f, double *F, int r)
{
// 离散余弦变换点数
long count;
// 循环变量
int i;
// 中间变量
double dTemp;
complex<double> *X;
// 计算离散余弦变换点数
count = 1<<r;
// 分配内存
X = new complex<double>[count*2];
// 赋初值为0
memset(X, 0, sizeof(complex<double>) * count * 2);
// 将时域点写入数组X
for(i=0;i<count;i++)
{
X[i] = complex<double> (f[i], 0);
}
// 调用快速付立叶变换
FFT(X,X,r+1);
// 调整系数
dTemp = 1/sqrt(count);
// 求F[0]
F[0] = X[0].real() * dTemp;
dTemp *= sqrt(2);
// 求F[u]
for(i = 1; i < count; i++)
{
F[i]=(X[i].real() * cos(i*PI/(count*2)) + X[i].imag() * sin(i*PI/(count*2))) * dTemp;
}
// 释放内存
delete X;
}/*************************************************************************
*
* 函数名称:
* DIBIFFT()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* long lWidth - 源图像宽度(象素数)
* long lHeight - 源图像高度(象素数)
* complex<double>*FD - 频域图象
* complex<double>*TD - 时域图象
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对经过FFT变换的图象进行反变换
*
************************************************************************/
bool DIBIFFT(BYTE * lpDIBBits,long lWidth,long lHeight,
complex<double>*FD,complex<double>*TD)
{
// 指向源图像的指针
unsigned char* lpSrc;
// 中间变量
double dTemp;
// 循环变量
long i;
long j;
// 进行付立叶变换的宽度和高度(2的整数次方)
long w;
long h; double dMin,dMax;
long lCount=0;
int wp;
int hp;
// 图像每行的字节数
long lLineBytes;
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行付立叶变换的宽度和高度(2的整数次方)
while(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while(h * 2 <= lHeight)
{
h *= 2;
hp++;
} // 计算图像每行的字节数
lLineBytes = WIDTHBYTES(w * 8);
FreqChange(FD,w,h);
for(i = 0; i < h; i++)
{
// 对y方向进行快速反付立叶变换
IFFT(&FD[w * i], &TD[w * i], wp);
}
// 保存变换结果
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
FD[ j*h+i ] = TD[ i*w+j ];
}
} for(i = 0; i < w; i++)
{
// 对x方向进行快速反付立叶变换
IFFT(&FD[i * h], &TD[i * h], hp);
}
/*******************倒序*********************/
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
FD[(h-1-i)*w+j] =TD[ i+h*j ];
}
}
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
TD[ i*w+j ] = FD[ i*w+j ];
}
}
/******************倒序*************************/ dMin = dMax = TD[0].real();
//应该显示实部
for( i=0;i<w*h;i++ )
{
if( dMin>TD[i].real() )
dMin = TD[i].real(); if( dMax<TD[i].real() )
dMax = TD[i].real();
} lCount = long (dMax - dMin);
// 行
for(i = 0; i < h; i++)
{
// 列
for(j = 0; j < w; j++)
{
//dTemp = (TD[(h-1-i)*w+j].real()-dMin)/lCount*255.0;
//dTemp = TD[(h-1-i)*w+j].real();
// 判断是否超过255
dTemp = abs(TD[(h-1-i)*w+j].real());
if (dTemp > 255)
{
// 对于超过的,直接设置为255
dTemp = 255;
}
// 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个象素的指针
// 此处不直接取i和j,是为了将变换后的原点移到中心
//lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
lpSrc = (unsigned char*)lpDIBBits + lLineBytes *
( h-1-i)+j; // (h - 1 - (i<h/2 ? i+h/2 : i-h/2))
// + (j<w/2 ? j+w/2 : j-w/2);
// 更新源图像
* (lpSrc) = (BYTE)(dTemp);
}
} // 返回
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* DIBFFT()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* long lWidth - 源图像宽度(象素数)
* long lHeight - 源图像高度(象素数)
* complex<double>*FD - 频域图象
* complex<double>*TD - 时域图象
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对时域图象进行FFT变换
*
************************************************************************/
bool DIBFFT(BYTE * lpDIBBits,long lWidth,long lHeight,
complex<double>*TD,complex<double>*FD)
{
// 指向源图像的指针
unsigned char* lpSrc;
// 中间变量
double dTemp;
// 循环变量
long i;
long j;
// 进行付立叶变换的宽度和高度(2的整数次方)
long w;
long h;
int wp;
int hp;
// 图像每行的字节数
long lLineBytes;
// 赋初值
w = 1;
h = 1;
wp = 0;
hp = 0;
// 计算进行付立叶变换的宽度和高度(2的整数次方)
while(w * 2 <= lWidth)
{
w *= 2;
wp++;
}
while(h * 2 <= lHeight)
{
h *= 2;
hp++;
} // 计算图像每行的字节数
lLineBytes = WIDTHBYTES(w * 8);
// 行
for(i = 0; i < h; i++)
{
// 列
for(j = 0; j < w; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 给时域赋值
TD[ i*w+j ] = complex<double>(*(lpSrc), 0);
}
}
for(i = 0; i < h; i++)
{
// 对y方向进行快速付立叶变换
FFT(&TD[w * i], &FD[w * i], wp);
}
// 保存变换结果
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
TD[i + h * j] = FD[ i*w+j ];
}
}
for(i = 0; i < w; i++)
{
// 对x方向进行快速付立叶变换
FFT(&TD[i * h], &FD[i * h], hp);
}/*******************倒序**********************/
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
TD[i*w+j] = FD[ i+h*j ];
}
}
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
FD[ i*w+j ] = TD[ i*w+j ];
}
}
/*******************倒序*************************/
FreqChange(FD,w,h);
// 行
for(i = 0; i < h; i++)
{
// 列
for(j = 0; j < w; j++)
{
// 计算频谱
dTemp = abs( FD[ (h-1-i)*w+j ] ) / 100;
// 判断是否超过255
if (dTemp > 255)
{
// 对于超过的,直接设置为255
dTemp = 255;
}
// 指向DIB第(i<h/2 ? i+h/2 : i-h/2)行,第(j<w/2 ? j+w/2 : j-w/2)个象素的指针
// 此处不直接取i和j,是为了将变换后的原点移到中心
//lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
lpSrc = (unsigned char*)lpDIBBits + lLineBytes *
( h-1-i)+j; // (h - 1 - (i<h/2 ? i+h/2 : i-h/2))
// + (j<w/2 ? j+w/2 : j-w/2);
// 更新源图像
* (lpSrc) = (BYTE)(dTemp);
}
} // 返回
return TRUE;}
这是我根据VC图象处理这本书改的,
包括了2维反FFT,
没错的!