- 编程实现2-d DFT正变换和反变换
- 频率域陷波滤波
实验代码
解决方案资源管理器如下:
FFT.h
#pragma once
void compute_W(int n, double* W_re, double* W_im);
void permute_bitrev(int n, double* A_re, double* A_im);
int bitrev(int inp, int numbits);
int log_2(int n);
void fft_butterfly(int n, double* A_re, double* A_im, double* W_re, double* W_im);
void fft_1d(int N, double* A_re, double* A_im);
void Notch(unsigned char* IYmoon, double* IYNotch,int moonheight, int moonwidth);
void Notch_2(double* IYmoon, double* IYNotch, int moonheight, int moonwidth);
void Notch_2(double* NY, double* IYNotch, int moonheight, int moonwidth);
void Change_Y(double* IYNotch, double* FFT2D_IM, double* FFT2D_RE, int moonheight, int moonwidth, int FFTheight,int FFTwidth);
void FFT_Column(double* FFT2D_RE, double* FFT2D_IM, int FFTheight, int FFTwidth);
void FFT_Row(double* FFT2D_RE, double* FFT2D_IM, int FFTheight, int FFTwidth);
void CreateH(double* H, int FFTheight, int FFTwidth);
void Filter(double* FFT2D_IM, double* FFT2D_RE, double* H, int FFTheight, int FFTwidth);
void Conjugate(double* FFT2D_IM, int FFTsize);
void Delete_zero(double* FFT2D_RE, double* NY, int FFTheight, int FFTwidth, int moonheight, int moonwidth);
fft.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include "FFT.h"
#define M_PI 3.1415926
void Notch(unsigned char* IYmoon, double* IYNotch, int moonheight, int moonwidth)
{
for (int i = 0; i < moonheight; i++)
{
for (int j = 0; j < moonwidth; j++)
{
IYNotch[i * moonwidth + j] = pow(-1,i+j) * double(IYmoon[i * moonwidth + j]);
}
}
}
void Notch_2(double* NY, double* IYNotch, int moonheight, int moonwidth)
{
for (int i = 0; i < moonheight; i++)
{
for (int j = 0; j < moonwidth; j++)
{
IYNotch[i * moonwidth + j] = pow(-1, i + j) * NY[i * moonwidth + j];
}
}
}
void Delete_zero(double* FFT2D_RE, double* NY, int FFTheight, int FFTwidth, int moonheight, int moonwidth)
{
for (int i = 0; i < moonheight; i++)
{
for (int j = 0; j < moonwidth; j++)
{
NY[i * moonwidth + j] = FFT2D_RE[i * FFTwidth + j]/((double)FFTheight*FFTwidth);
}
}
}
void Change_Y(double* IYNotch, double* FFT2D_IM, double* FFT2D_RE, int moonheight, int moonwidth, int FFTheight, int FFTwidth)
{
for (int i = 0; i < FFTheight; i++)
{
for (int j = 0; j < FFTwidth; j++)
{
if (i < moonheight && j < moonwidth)
{
FFT2D_RE[i * FFTwidth + j] = IYNotch[i * moonwidth + j];
}
else
FFT2D_RE[i * FFTwidth + j] = 0;
}
}
}
void FFT_Column(double* FFT2D_RE, double* FFT2D_IM, int FFTheight, int FFTwidth)
{
for (int i = 0; i < FFTwidth; i++)
{
double* A_re = new double[sizeof(double) * FFTheight];
double* A_im = new double[sizeof(double) * FFTheight];
for (int k = 0; k < FFTheight; k++)
{
A_re[k] = FFT2D_RE[k * FFTwidth + i];
A_im[k] = FFT2D_IM[k * FFTwidth + i];
}
fft_1d(FFTheight, A_re, A_im);
for (int k = 0; k < FFTheight; k++)
{
FFT2D_RE[k * FFTwidth + i] = A_re[k];
FFT2D_IM[k * FFTwidth + i] = A_im[k];
}
delete[]A_re;
delete[]A_im;
}
}
void FFT_Row(double* FFT2D_RE, double* FFT2D_IM, int FFTheight, int FFTwidth)
{
for (int i = 0; i < FFTheight; i++)
{
double* A_re = new double[sizeof(double) * FFTwidth];
double* A_im = new double[sizeof(double) * FFTwidth];
for (int k = 0; k < FFTwidth; k++)
{
A_re[k] = FFT2D_RE[i * FFTwidth + k];
A_im[k] = FFT2D_IM[i * FFTwidth + k];
}
fft_1d(FFTwidth, A_re, A_im);
for (int k = 0; k < FFTwidth; k++)
{
FFT2D_RE[i * FFTwidth + k] = A_re[k];
FFT2D_IM[i * FFTwidth + k] = A_im[k];
}
delete[]A_re;
delete[]A_im;
}
}
void Filter(double* FFT2D_IM, double* FFT2D_RE, double* H, int FFTheight, int FFTwidth)
{
for (int i = 0; i < FFTheight; i++)
{
for (int j = 0; j < FFTwidth; j++)
{
FFT2D_IM[i * FFTwidth + j] = FFT2D_IM[i * FFTwidth + j] * H[i * FFTwidth + j];
}
}
}
void CreateH(double* H, int FFTheight, int FFTwidth)
{
for (int i = 0; i < FFTheight; i++)
{
for (int j = 0; j < FFTwidth; j++)
{
H[i * FFTwidth + j] = 1.5;
if ((i == FFTheight / 2) && (j == FFTwidth / 2))
{
H[i * FFTwidth + j] = 0.5;
}
}
}
}
void Conjugate(double* FFT2D_IM, int FFTsize)
{
for (int i = 0; i < FFTsize; i++)
{
FFT2D_IM[i] = -FFT2D_IM[i];
}
}
void fft_1d(int N, double* A_re, double* A_im)
{
double* W_re, * W_im;
W_re = (double*)malloc(sizeof(double) * N / 2);
W_im = (double*)malloc(sizeof(double) * N / 2);
assert(W_re != NULL && W_im != NULL);
compute_W(N, W_re, W_im);
fft_butterfly(N, A_re, A_im, W_re, W_im);
permute_bitrev(N, A_re, A_im);
free(W_re);
free(W_im);
}
void compute_W(int n, double* W_re, double* W_im)
{
int i, br;
int log2n = log_2(n);
for (i = 0; i < (n / 2); i++)
{
br = bitrev(i, log2n - 1);
W_re[br] = cos(((double)i * 2.0 * M_PI) / ((double)n));
W_im[br] = -sin(((double)i * 2.0 * M_PI) / ((double)n));
}
}
void permute_bitrev(int n, double* A_re, double* A_im)
{
int i, bri, log2n;
double t_re, t_im;
log2n = log_2(n);
for (i = 0; i < n; i++)
{
bri = bitrev(i, log2n);
if (bri <= i) continue;
t_re = A_re[i];
t_im = A_im[i];
A_re[i] = A_re[bri];
A_im[i] = A_im[bri];
A_re[bri] = t_re;
A_im[bri] = t_im;
}
}
int bitrev(int inp, int numbits)
{
int i, rev = 0;
for (i = 0; i < numbits; i++)
{
rev = (rev << 1) | (inp & 1);
inp >>= 1;
}
return rev;
}
int log_2(int n)
{
int res;
for (res = 0; n >= 2; res++)
n = n >> 1;
return res;
}
void fft_butterfly(int n, double* A_re, double* A_im, double* W_re, double* W_im)
{
double w_re, w_im, u_re, u_im, t_re, t_im;
int m, g, b;
int mt, k;
for (m = n; m >= 2; m = m >> 1)
{
mt = m >> 1;
for (g = 0, k = 0; g < n; g += m, k++)
{
w_re = W_re[k];
w_im = W_im[k];
for (b = g; b < (g + mt); b++)
{
t_re = w_re * A_re[b + mt] - w_im * A_im[b + mt];
t_im = w_re * A_im[b + mt] + w_im * A_re[b + mt];
u_re = A_re[b];
u_im = A_im[b];
A_re[b] = u_re + t_re;
A_im[b] = u_im + t_im;
A_re[b + mt] = u_re - t_re;
A_im[b + mt] = u_im - t_im;
}
}
}
}
main.cpp
#include
#include
#include
#include "FFT.h"
using namespace std;
int main()
{
int moonwidth = 464;
int moonheight = 538;
int FFTwidth = 512;
int FFTheight = 1024;
int FFTsize = FFTheight * FFTwidth;
int moonsize = moonheight * moonwidth * 3;
int moonYsize = moonheight * moonwidth;
int moonEsize = moonheight * moonwidth * 2;
ifstream Imoonfile("moon.yuv", ios::binary);
ofstream Omoonfile("outmoon.yuv", ios::binary);
if (!Imoonfile) { cout << "error to open moonfile!" << endl; }
if (!Omoonfile) { cout << "error to create moonfile!" << endl; }
unsigned char* IYmoon = new unsigned char[moonYsize];
unsigned char* IEmoon = new unsigned char[moonEsize];
unsigned char* OYmoon = new unsigned char[moonYsize];
double* IYNotch = new double[moonYsize];
double* FFT2D_RE = new double[FFTsize];
double* FFT2D_IM = new double[FFTsize];
double* NY = new double[moonYsize];
Imoonfile.read((char*)IYmoon, moonYsize);
Imoonfile.read((char*)IEmoon, moonEsize);
Notch(IYmoon,IYNotch, moonheight,moonwidth);
Change_Y(IYNotch, FFT2D_IM, FFT2D_RE,moonheight,moonwidth,FFTheight,FFTwidth);
FFT_Column(FFT2D_RE,FFT2D_IM, FFTheight, FFTwidth);
FFT_Row(FFT2D_RE, FFT2D_IM, FFTheight, FFTwidth);
double* H = new double[FFTsize];
CreateH(H,FFTheight,FFTwidth);
Filter(FFT2D_IM, FFT2D_RE, H, FFTheight, FFTwidth);
Conjugate(FFT2D_IM, FFTsize);
FFT_Column(FFT2D_RE, FFT2D_IM, FFTheight, FFTwidth);
FFT_Row(FFT2D_RE, FFT2D_IM, FFTheight, FFTwidth);
Conjugate(FFT2D_IM, FFTsize);
Delete_zero(FFT2D_RE, NY, FFTheight, FFTwidth, moonheight, moonwidth);
Notch_2(NY, IYNotch, moonheight, moonwidth);
for (int i = 0; i < moonheight; i++)
{
for (int j = 0; j < moonwidth; j++)
{
if (IYNotch[i * moonwidth + j] > 255)
{
IYNotch[i * moonwidth + j] = 255;
}
else if (IYNotch[i * moonwidth + j] < 0)
{
IYNotch[i * moonwidth + j] = 0;
}
OYmoon[i * moonwidth + j] = unsigned char(IYNotch[i * moonwidth + j]);
}
}
Omoonfile.write((char*)OYmoon, moonYsize);
Omoonfile.write((char*)IEmoon, moonEsize);
delete[]IYmoon;
delete[]IEmoon;
delete[]IYNotch;
delete[]FFT2D_IM;
delete[]FFT2D_RE;
delete[]NY;
delete[]H;
Imoonfile.close();
Omoonfile.close();
return 0;
}
实验结果
至此,实验结束。