FFT算法原理就不解释了,可以搜索一下百度即可。
在二维变换中,需要对矩阵进行一行一行,一列一列的FFT变换,具体公式为:
F(u,v)=sum(i=0->M-1)sum(j=0->N-1)f(i, j) * exp(-j2πui/M-j*2πvj/N)
也就可以表示为:F(u,v)=sum(i=0->M-1) * exp(-j*2πu*i*/M) * sum(j=0->N-1)f(i, j) * exp(-j*2πv*j/N)
剩下的就是两个for循环了,具体阅读代码吧。
#include "iostream"
#include <stdlib.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define SIZE 256
#define VALUE_MAX 256
using namespace std;
/***************复数运算*****************/
typedef struct Complex{
float real;
float imagin;
};
//定义复数计算,包括乘法,加法,减法
void Add_Complex(Complex * src1,Complex *src2,Complex *dst){
dst->imagin=src1->imagin+src2->imagin;
dst->real=src1->real+src2->real;
}
void Sub_Complex(Complex * src1,Complex *src2,Complex *dst){
dst->imagin=src1->imagin-src2->imagin;
dst->real=src1->real-src2->real;
}
void Multy_Complex(Complex * src1,Complex *src2,Complex *dst){
float r1=0.0,r2=0.0;
float i1=0.0,i2=0.0;
r1=src1->real;
r2=src2->real;
i1=src1->imagin;
i2=src2->imagin;
dst->imagin=r1*i2+r2*i1;
dst->real=r1*r2-i1*i2;
}
//exp(-j2pi/N)
void getWN(float n,int size_n,Complex * dst){
float x=2.0*M_PI*n/size_n;
dst->imagin=-sin(x);
dst->real=cos(x);
}
//定义DFT函数,利用DFT定义
void DFT(float * src,Complex * dst,int size){
for(int m=0;m<size;m++){
float real=0.0;
float imagin=0.0;
for(int n=0;n<size;n++){
float x=M_PI*2*m*n;
real+=src[n]*cos(x/size);
imagin+=src[n]*(-sin(x/size));
}
dst[m].imagin=imagin;
dst[m].real=real;
}
}
//定义IDFT函数
void IDFT(Complex *src,Complex *dst,int size){
for(int m=0;m<size;m++){
float real=0.0;
float imagin=0.0;
for(int n=0;n<size;n++){
float x=M_PI*2*m*n/size;
real+=src[n].real*cos(x)-src[n].imagin*sin(x);
imagin+=src[n].real*sin(x)+src[n].imagin*cos(x);
}
real/=size;
imagin/=size;
if(dst!=NULL){
dst[m].real=real;
dst[m].imagin=imagin;
}
}
}
//序数重排
int FFT_remap(float * src,int size_n){
if(size_n==1)
return 0;
float * temp=(float *)malloc(sizeof(float)*size_n);
for(int i=0;i<size_n;i++)
if(i%2==0)
temp[i/2]=src[i];
else
temp[(size_n+i)/2]=src[i];
for(int i=0;i<size_n;i++)
src[i]=temp[i];
free(temp);
FFT_remap(src, size_n/2);
FFT_remap(src+size_n/2, size_n/2);
return 1;
}
int FFT_remap(Complex * src,int size_n){
if(size_n==1)
return 0;
Complex * temp=(Complex *)malloc(sizeof(Complex)*size_n);
for(int i=0;i<size_n;i++)
if(i%2==0)
temp[i/2]=src[i];
else
temp[(size_n+i)/2]=src[i];
for(int i=0;i<size_n;i++)
src[i]=temp[i];
free(temp);
FFT_remap(src, size_n/2);
FFT_remap(src+size_n/2, size_n/2);
return 1;
}
//定义FFT
void FFT(float * src,Complex * dst,int size_n){
FFT_remap(src, size_n);
int k=size_n;
int z=0;
while (k/=2) {
z++;
}
k=z;
if(size_n!=(1<<k))
exit(0);
Complex * src_com=(Complex*)malloc(sizeof(Complex)*size_n);
if(src_com==NULL)
exit(0);
for(int i=0;i<size_n;i++){
src_com[i].real=src[i];
src_com[i].imagin=0;
}
for(int i=0;i<k;i++){
z=0;
for(int j=0;j<size_n;j++){
if((j/(1<<i))%2==1){
Complex wn;
getWN(z, size_n, &wn);
Multy_Complex(&src_com[j], &wn,&src_com[j]);
z+=1<<(k-i-1);
Complex temp;
int neighbour=j-(1<<(i));
temp.real=src_com[neighbour].real;
temp.imagin=src_com[neighbour].imagin;
Add_Complex(&temp, &src_com[j], &src_com[neighbour]);
Sub_Complex(&temp, &src_com[j], &src_com[j]);
}
else
z=0;
}
}
for(int i=0;i<size_n;i++){
dst[i].imagin=src_com[i].imagin;
dst[i].real=src_com[i].real;
}
}
void FFT(Complex * src,Complex * dst,int size_n){
FFT_remap(src, size_n);
int k=size_n;
int z=0;
while (k/=2) {
z++;
}
k=z;
if(size_n!=(1<<k))
exit(0);
Complex * src_com=(Complex*)malloc(sizeof(Complex)*size_n);
if(src_com==NULL)
exit(0);
for(int i=0;i<size_n;i++){
src_com[i].real=src[i].real;
src_com[i].imagin=src[i].imagin;
}
for(int i=0;i<k;i++){
z=0;
for(int j=0;j<size_n;j++){
if((j/(1<<i))%2==1){
Complex wn;
getWN(z, size_n, &wn);
Multy_Complex(&src_com[j], &wn,&src_com[j]);
z+=1<<(k-i-1);
Complex temp;
int neighbour=j-(1<<(i));
temp.real=src_com[neighbour].real;
temp.imagin=src_com[neighbour].imagin;
Add_Complex(&temp, &src_com[j], &src_com[neighbour]);
Sub_Complex(&temp, &src_com[j], &src_com[j]);
}
else
z=0;
}
}
for(int i=0;i<size_n;i++){
dst[i].imagin=src_com[i].imagin;
dst[i].real=src_com[i].real;
}
}
void IFFT(Complex * src,Complex * dst,int size_n){
FFT_remap(src, size_n);
int k=size_n;
int z=0;
while (k/=2) {
z++;
}
k=z;
if(size_n!=(1<<k))
exit(0);
Complex * src_com=(Complex*)malloc(sizeof(Complex)*size_n);
if(src_com==NULL)
exit(0);
for(int i=0;i<size_n;i++){
src_com[i].real=src[i].real;
src_com[i].imagin=src[i].imagin;
}
for(int i=0;i<k;i++){
z=0;
for(int j=0;j<size_n;j++){
if((j/(1<<i))%2==1){
Complex wn;
getWN(-1.0*z, size_n, &wn);
Multy_Complex(&src_com[j], &wn,&src_com[j]);
z+=1<<(k-i-1);
Complex temp;
int neighbour=j-(1<<(i));
temp.real=src_com[neighbour].real;
temp.imagin=src_com[neighbour].imagin;
Add_Complex(&temp, &src_com[j], &src_com[neighbour]);
Sub_Complex(&temp, &src_com[j], &src_com[j]);
}
else
z=0;
}
}
for(int i=0;i<size_n;i++){
dst[i].imagin=src_com[i].imagin/size_n;
dst[i].real=src_com[i].real/size_n;
}
}
void FFT_2D(float** temp, Complex **get, int size_n)
{
// float temp[SIZE][SIZE] = { 0.0 };//存储图像数组
float tempreal[SIZE][SIZE] = { 0.0 };//存储图像数组变换后的实部
float tempimage[SIZE][SIZE] = { 0.0 };//存储图像数组变换后的虚部
Complex src[SIZE];
Complex dst[SIZE];
///对图像进行傅里叶变换
//进行每一行的FFT变换
for (int i = 0; i < SIZE; i++)
{
FFT(temp[i], dst, SIZE);//得到256长度复数数组dst
for (int j = 0; j < SIZE; j++)
{
tempreal[i][j] = dst[j].real;//存储实部
tempimage[i][j] = dst[j].imagin;//存储虚部
}
}
//对已经进行行变换后的复数数组再进行列fft变换
for (int j = 0; j<SIZE; j++)
{
for (int i = 0; i<SIZE; i++)//列复制
{
src[i].real = tempreal[i][j];
src[i].imagin = tempimage[i][j];
}//复制好第j列到src[SIZE]
FFT(src, dst, SIZE);
for (int i = 0; i<SIZE; i++)
{
tempreal[i][j] = dst[i].real;//把对第j列进行的fft再次填到原来的数组
tempimage[i][j] = dst[i].imagin;
}
}//得到各个j列的fft变换,也就是图像的fft变换tempreal+j*tempimage = F(u,v)
//再次输出变换后的某一个值
cout << tempreal[10][10] << "+j" << tempimage[10][10] << endl;
/********************************************
****************进行反傅里叶变换*************
*********************************************/
//对i行,每一行进行一维傅里叶变换
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
//把F(u,v)每一行,这里是第i行存储到Complex 一维数组src
src[j].real = tempreal[i][j];
src[j].imagin = tempimage[i][j];
}
IFFT(src, dst, SIZE);
FFT_remap(dst, SIZE);
for (int j = 0; j < SIZE; j++)
{
tempreal[i][j] = dst[j].real;
tempimage[i][j] = dst[j].imagin;
}
}
//现在进行列变化
for (int j = 0; j < SIZE; j++)
{
for (int i = 0; i < SIZE; i++)
{
src[i].real = tempreal[i][j];
src[i].imagin = tempimage[i][j];
}//复制好每一列
IFFT(src, dst, SIZE);
FFT_remap(dst, SIZE);
for (int i = 0; i < SIZE; i++)
{
get[i][j].real = dst[i].real; //tempreal[i][j] = dst[i].real;
get[i][j].imagin = dst[i].imagin; //tempimage[i][j] = dst[i].imagin;
}
}
}
/*end 复数运算*******************************/
int main(int argc, const char * argv[]) {
float input[SIZE];
float temp[SIZE][SIZE] = {0.0};//存储图像数组,可以导入,也可以赋初值
float tempreal[SIZE][SIZE] = { 0.0 };//存储图像数组变换后的实部
float tempimage[SIZE][SIZE] = { 0.0 };//存储图像数组变换后的虚部
Complex src[SIZE];
Complex dst[SIZE];
/****************************************/
///对图像进行傅里叶变换
//进行每一行的FFT变换
for (int i = 0; i < SIZE; i++)
{
FFT(temp[i], dst, SIZE);//得到256长度复数数组dst
for (int j = 0; j < SIZE; j++)
{
tempreal[i][j] = dst[j].real;//存储实部
tempimage[i][j] = dst[j].imagin;//存储虚部
}
}
//对已经进行行变换后的复数数组再进行列fft变换
for(int j=0;j<SIZE;j++)
{
for(int i=0;i<SIZE;i++)//列复制
{
src[i].real = tempreal[i][j];
src[i].imagin = tempimage[i][j];
}//复制好第j列到src[SIZE]
FFT(src,dst,SIZE);
for(int i=0;i<SIZE;i++)
{
tempreal[i][j]=dst[i].real;//把对第j列进行的fft再次填到原来的数组
tempimage[i][j]=dst[i].imagin;
}
}//得到各个j列的fft变换,也就是图像的fft变换tempreal+j*tempimage = F(u,v)
/*************** 低通滤波 ***************/
/*for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
if (sqrt(pow(tempreal[i][j], 2) + pow(tempimage[i][j], 2)) < 1000)
tempreal[i][j] = tempimage[i][j] = 0.0;
}
*/
/************** 高通滤波 *****************/
/*for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
if (sqrt(pow(tempreal[i][j], 2) + pow(tempimage[i][j], 2)) > 4000)
tempreal[i][j] = tempimage[i][j] = 0.0;
}
*/
/*******************附加一个反变换的算法*******************
****************进行反傅里叶变换*************
*********************************************/
//对i行,每一行进行一维傅里叶变换
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
//把F(u,v)每一行,这里是第i行存储到Complex 一维数组src
src[j].real = tempreal[i][j];
src[j].imagin = tempimage[i][j];
}
IFFT(src, dst, SIZE);
FFT_remap(dst, SIZE);
for (int j = 0; j < SIZE; j++)
{
tempreal[i][j] = dst[j].real;
tempimage[i][j] = dst[j].imagin;
}
}
//现在进行列变化
for (int j = 0; j < SIZE; j++)
{
for (int i = 0; i < SIZE; i++)
{
src[i].real = tempreal[i][j];
src[i].imagin = tempimage[i][j];
}//复制好每一列
IFFT(src, dst, SIZE);
FFT_remap(dst, SIZE);
for (int i = 0; i < SIZE; i++)
{
tempreal[i][j] = dst[i].real;
tempimage[i][j] = dst[i].imagin;
}
}
/***************************************/
//对比输出一下,选择前20X20矩阵
cout << "\n\n**************************************\n\n";
for (int i = 0; i < 20; i++)
{
for (int j = 0; j <10; j++)
{
cout << temp[i][j] << '\t' << tempreal[i][j] << '\t' << tempimage[i][j] << endl;
}
cout << endl;
}
putchar('\n');
return 0;
}