/**
* 2D-IDFT [Inverse Discrete Fourier Transform]
* [How to Use]
* <case:>
* Fo[W][H] = {};
* Fn[U][V] = {...};
* idft_2d(&Fo, &Fn);
* [logistic]
* {
* result[W][H] = []; // as byte 2D-array
* // do SDD:
* for y in Range(Height) {
* for x in Range(Wight) {
* Re = 0; Im = 0;
* // do FDD:
* for u in range(NU-Horizontal_Slices) {
* for v in range(NV-Vertical_Slices) {
* Wn = (2 * PI) * Vec< (u / U , v / V)>;;
* An = Re * (Fn[n] · Vec<x,y>T);
* Bn = Im * (Fn[n] · Vec<x,y>T);
* result[t] += Fn[n].to_value(Wn, An, Bn) / (U * V);
* }}
* }
* return result;
* }
* @param original_ Original Function input 2D-array
* (image include width & height)
* @param analyzed_ Fourier Basis analyzed info in 2D
*/
接下来只需要根据思路做代码实现即可:
#include "stdio.h"
#include "math.h"
#define PI 3.1415926f
typedef struct FBasis {
double re_;
double im_;
double w_[2];
} FBasis;
typedef struct Signal2DOriginal {
int GW_;
int GH_;
double *Fo_;
} Signal2DOriginal;
typedef struct Signal2DAnalyzed {
int NU_;
int NV_;
FBasis *Fn_;
} Signal2DAnalyzed;
void dft_2d(Signal2DOriginal *original_, Signal2DAnalyzed *analyzed_) {
for (int u = 0; u < analyzed_->NU_; ++u) {
for (int v = 0; v < analyzed_->NV_; ++v) {
double An = 0;
double Bn = 0;
double Un = (2 * PI / analyzed_->NU_) * u ;
double Vn = (2 * PI / analyzed_->NV_) * v ;
for (int y = 0; y < original_->GH_; ++y) {
for (int x = 0; x < original_->GW_; ++x) {
An += cos(Un * x + Vn * y) * original_->Fo_[y * original_->GW_ + x];
Bn += sin(Un * x + Vn * y) * original_->Fo_[y * original_->GW_ + x];
}
}
FBasis e_ = {An, Bn, {Un, Vn}};
analyzed_->Fn_[u * analyzed_->NV_ + v] = e_;
}
}
}
void idft_2d(Signal2DOriginal *original_, Signal2DAnalyzed *analyzed_) {
for (int y = 0; y < original_->GH_; ++y) {
for (int x = 0; x < original_->GW_; ++x) {
for (int u = 0; u < analyzed_->NU_; ++u) {
for (int v = 0; v < analyzed_->NV_; ++v) {
FBasis e_ = analyzed_->Fn_[u * analyzed_->NV_ + v];
original_->Fo_[y * original_->GW_ + x] += (
e_.re_ * cos(e_.w_[0] * x + e_.w_[1] * y) +
e_.im_ * sin(e_.w_[0] * x + e_.w_[1] * y)
) / (analyzed_->NU_ * analyzed_->NV_);
}
}
}
}
}
写完后还是需要简单测试一下:
int main(void) {
double input_data_[36] = {
1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f,
2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 1.0f,
3.0f, 4.0f, 5.0f, 6.0f, 1.0f, 2.0f,
4.0f, 5.0f, 6.0f, 1.0f, 2.0f, 3.0f,
5.0f, 6.0f, 1.0f, 2.0f, 3.0f, 4.0f,
6.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f
};
FBasis output_data_[36] = {};
double versed_data_[36] = {};
Signal2DOriginal Fo = {
6, 6,
input_data_
};
Signal2DAnalyzed Fn = {
6, 6,
output_data_
};
Signal2DOriginal iFo = {
6, 6,
versed_data_
};
printf("\n Original_data: \n");
for (int y = 0; y < Fo.GH_; ++y) {
for (int x = 0; x < Fo.GW_; ++x) {
printf("%f ", Fo.Fo_[x + y * Fo.GW_]);
}
printf("\n");
}
printf("\n DFT_result: \n");
dft_2d(&Fo, &Fn);
for (int v = 0; v < Fn.NV_; ++v) {
for (int u = 0; u < Fn.NU_; ++u) {
printf("%.3f + i %.3f ",
Fn.Fn_[u + v * Fn.NU_].re_,
Fn.Fn_[u + v * Fn.NU_].im_
);
}
printf("\n");
}
printf("\n IDFT_result: \n");
idft_2d(&iFo, &Fn);
for (int y = 0; y < iFo.GH_; ++y) {
for (int x = 0; x < iFo.GW_; ++x) {
printf("%f ", iFo.Fo_[x + y * Fo.GW_]);
}
printf("\n");
}
return 0;
}
得到结果和标准几近相同:
Original_data:
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000
2.000000 3.000000 4.000000 5.000000 6.000000 1.000000
3.000000 4.000000 5.000000 6.000000 1.000000 2.000000
4.000000 5.000000 6.000000 1.000000 2.000000 3.000000
5.000000 6.000000 1.000000 2.000000 3.000000 4.000000
6.000000 1.000000 2.000000 3.000000 4.000000 5.000000
DFT_result:
126.000 + i 0.000 -0.000 + i 0.000 -0.000 + i 0.000 0.000 + i 0.000 0.000 + i 0.000 0.000 + i 0.000
-0.000 + i 0.000 -18.000 + i -31.177 0.000 + i 0.000 0.000 + i -0.000 0.000 + i -0.000 0.000 + i -0.000
-0.000 + i 0.000 0.000 + i 0.000 -18.000 + i -10.392 0.000 + i -0.000 0.000 + i -0.000 0.000 + i -0.000
0.000 + i 0.000 0.000 + i -0.000 0.000 + i -0.000 -18.000 + i 0.000 0.000 + i -0.000 -0.000 + i -0.000
0.000 + i 0.000 0.000 + i -0.000 0.000 + i -0.000 0.000 + i -0.000 -18.000 + i 10.392 -0.000 + i -0.000
0.000 + i 0.000 0.000 + i -0.000 0.000 + i -0.000 -0.000 + i -0.000 -0.000 + i -0.000 -18.000 + i 31.177
IDFT_result:
1.000007 2.000001 2.999999 3.999999 5.000001 6.000003
2.000001 2.999998 3.999998 4.999998 5.999999 1.000000
2.999999 3.999998 4.999997 5.999998 0.999998 2.000000
3.999999 4.999998 5.999998 0.999997 1.999999 3.000001
5.000001 5.999999 0.999998 1.999999 3.000000 4.000003
6.000003 1.000000 2.000000 3.000001 4.000003 5.000005
运行结束。
二维离散傅里叶变换到此结束,那么更多维度的傅里叶变换该怎么处理呢?我们只需要拓展波矢 k 的维度即可。而多维和一维、二维情况,在离散傅里叶变换的逻辑流程上并没有不同。但是,随着波矢 k 的参数维度扩展,我们发现现有的直接计算法实现的离散傅里叶变换,其算法时间复杂度 O{n2} 已不足以支撑超过二维参数量后的敏捷计算。因此,我们迫切需要一种更快的代替算法。