傅立葉變換C++模式
阿新 • • 發佈:2018-11-23
三組傅立葉變換和反變換的程式碼
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <iostream> #include <fstream> #include <vector> #include <ctime> #include <iomanip> using namespace std; #define PI 3.14159265 #define N 4095 //取樣256次 typedef struct //定義結構體 { double real;/*實部*/ double img;/*虛部*/ }complex; complex x[N * 2], *W; /*輸出序列的值*/ //序列長度 全域性變數 void add(complex a, complex b, complex *c) // 複數加運算 { c->real = a.real + b.real; c->img = a.img + b.img; } void sub(complex a, complex b, complex *c) // 複數減運算 { c->real = a.real - b.real; c->img = a.img - b.img; } void mul(complex a, complex b, complex *c) //複數乘運算 { c->real = a.real*b.real - a.img*b.img; c->img = a.real*b.img + a.img*b.real; } void divi(complex a, complex b, complex *c) // 複數除運算 { c->real = (a.real*b.real + a.img*b.img) / (b.real*b.real + b.img*b.img); c->img = (a.img*b.real - a.real*b.img) / (b.real*b.real + b.img*b.img); } void initW(int size) //尤拉公式運算 { int i; W = (complex*)malloc(sizeof(complex)* size); //分配記憶體空間 for (i = 0; i<size; i++) { W[i].real = cos(2 * PI / size*i); W[i].img = -1 * sin(2 * PI / size*i); } /*for (i = 0; i < size; i++) { cout << endl; cout << endl; cout << endl; cout << W[i].real << " "; cout << W[i].img <<"j" << " "; }*/ } void changex(int size) //變址運算 { complex temp; unsigned int i = 0, j = 0, k = 0; double t; for (i = 0; i<size; i++) { k = i; j = 0; t = (log(size) / log(2)); while ((t--)>0) { j = j << 1; j |= (k & 1); k = k >> 1; } if (j>i) { temp = x[i]; x[i] = x[j]; x[j] = temp; } } } void fftx() //快速傅立葉函式 { long int i = 0, j = 0, k = 0, l = 0; complex up, down, product; changex(N); for (i = 0; i<log(N) / log(2); i++) /*一級蝶形運算*/ { l = 1 << i; for (j = 0; j<N; j += 2 * l) /*一組蝶形運算*/ { for (k = 0; k<l; k++) /*一個蝶形運算*/ { mul(x[j + k + l], W[N*k / 2 / l], &product); add(x[j + k], product, &up); sub(x[j + k], product, &down); x[j + k] = up; x[j + k + l] = down; } } } } void output() /*輸出x結果*/ { int i; printf("\nx傅立葉變換結果\n"); for (i = 0; i<N; i++) { if (i % 4 == 0 && i != 0) printf("\n"); printf(" %.2f", x[i].real); if (x[i].img >= 0.0001) printf("+%.2fj ", x[i].img); else if (fabs(x[i].img)<0.0001) printf("+0.0000j "); else printf("%.2fj ", x[i].img); } printf("\n"); } /*void save() //儲存x傅立葉變換結果 { int i; ofstream outfile("D:\\result1.txt", ios::out); if (!outfile) { cerr << "open result1.txt erro!" << endl; exit(1); } outfile << "x傅立葉變換結果:" << endl; for (i = 0; i<N; i++) { outfile << x[i].real; if (x[i].img >= 0.0001) outfile << "+" << x[i].img << "j" << " "; else if (fabs(x[i].img)<0.0001) outfile << "+" << "0.00" << "j" << " "; else outfile << x[i].img << "j" << " "; } printf("\n"); outfile.close(); }*/ int main() { clock_t start = clock(); double duration; /*對x進行傅立葉變換*/ int i, j = 0, t = 0; double data[N * 2] = { 0 }; double result[N * 2] = { 0 }; float tx = 0; //ofstream outfile1("D:\\result.txt", ios::out); for (t = 0; t < N; t++) { data[t] = 5 + 7 * cos(30 * PI / 128 * t - 30 * PI / 180) + 3 * cos(80 * PI / 128 * t - 90 * PI / 180); } for (i = 0; i<N; i++) //求出x的256個取樣點的值 下一步傅立葉變化 { x[i].real = data[i]; x[i].img = 0; //printf("%.4f ", x[i].real); //printf("%.4f ", x[i].img); } initW(N); fftx(); //output(); cout << "輸出訊號的模"; cout << endl; for (i = 0; i < N; i++) { result[i] = sqrt(x[i].real*x[i].real + x[i].img*x[i].img); if (i % 4 == 0) cout << endl; cout << setprecision(2) << result[i] / N * 2 << " "; //outfile1 << result[i] / N * 2 << endl; } //save(); clock_t end = clock(); cout << "所用的時間: "; duration = (double)(end - start) / CLOCKS_PER_SEC; cout << duration << "ms"; cout << endl; return 0; }
傅立葉變換,加入一個低通濾波器
// fourie2.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <math.h> #include <malloc.h> #include <iostream> #include <istream> #include <fstream> #include <sstream> #include <string> #include <vector> #define pi (double) 3.14159265359 #define POWER 9 using namespace std; /*複數的定義*/ typedef struct { double re; double im; }COMPLEX; /*複數的加運算*/ COMPLEX Add(COMPLEX c1, COMPLEX c2) { COMPLEX c; c.re = c1.re + c2.re; c.im = c1.im + c2.im; return c; } /*負數的減運算*/ COMPLEX Sub(COMPLEX c1, COMPLEX c2) { COMPLEX c; c.re = c1.re - c2.re; c.im = c1.im - c2.im; return c; } /*複數的乘運算*/ COMPLEX Mul(COMPLEX c1, COMPLEX c2) { COMPLEX c; c.re = c1.re*c2.re - c1.im*c2.im; c.im = c1.re*c2.im + c1.im*c2.re; return c; } /*快速傅立葉變換 TD為時域值,FD為頻域值,power為2的冪數*/ void FFT(COMPLEX *TD, COMPLEX *FD, int power) { int count; int i, j, k, bfsize, p; double angle; COMPLEX *W, *X1, *X2, *X; /*計算傅立葉變換點數*/ count = 1 << power; /*分配運算器所需儲存器*/ W = (COMPLEX *)malloc(sizeof(COMPLEX)*count / 2); X1 = (COMPLEX *)malloc(sizeof(COMPLEX)*count); X2 = (COMPLEX *)malloc(sizeof(COMPLEX)*count); /*計算加權係數*/ for (i = 0; i<count / 2; i++) { angle = -i*pi * 2 / count; W[i].re = cos(angle); W[i].im = sin(angle); } /*將時域點寫入儲存器*/ memcpy(X1, TD, sizeof(COMPLEX)*count); /*蝶形運算*/ for (k = 0; k<power; k++) { for (j = 0; j<1 << k; j++) { bfsize = 1 << power - k; for (i = 0; i<bfsize / 2; i++) { p = j*bfsize; X2[i + p] = Add(X1[i + p], X1[i + p + bfsize / 2]); X2[i + p + bfsize / 2] = Mul(Sub(X1[i + p], X1[i + p + bfsize / 2]), W[i*(1 << k)]); } } X = X1; X1 = X2; X2 = X; } /*重新排序*/ cout << "頻域" << endl; vector<float> aa; for (j = 0; j<count; j++) { p = 0; for (i = 0; i<power; i++) { if (j&(1 << i)) p += 1 << power - i - 1; } FD[j] = X1[p]; cout << FD[j].re << endl; aa.push_back(FD[j].re); } /*釋放儲存器*/ free(W); free(X1); free(X2); } /*快速傅立葉反變換,利用快速傅立葉變換 FD為頻域值,TD為時域值,power為2的冪數*/ void IFFT(COMPLEX *FD, COMPLEX *TD, int power) { int i, count; COMPLEX *x; /*計算傅立葉反變換點數*/ count = 1 << power; /*分配運算所需儲存器*/ x = (COMPLEX *)malloc(sizeof(COMPLEX)*count); /*將頻域點寫入儲存器*/ memcpy(x, FD, sizeof(COMPLEX)*count); /*求頻域點的共軛*/ for (i = 0; i<count; i++) { x[i].im = -x[i].im; } /*呼叫快速傅立葉變換*/ FFT(x, TD, power); /*求時域點的共軛*/ cout << "反變換" << endl; for (i = 0; i<count; i++) { TD[i].re /= count; TD[i].im = -TD[i].im / count; cout << TD[i].re << endl; } /*釋放儲存器*/ free(x); } float min(float a, float b) { return a < b ? a : b; } void convolution(double *input1, double *input2, double *output, int mm, int nn) { double *xx = new double[mm + nn - 1]; double *tempinput2 = new double[mm + nn - 1]; for (int i = 0; i < nn; i++) { tempinput2[i] = input2[i]; } for (int i = nn; i < mm + nn - 1; i++) { tempinput2[i] = 0.0; } // do convolution for (int i = 0; i < mm + nn - 1; i++) { xx[i] = 0.0; int tem = (min(i, mm)) == mm ? mm - 1 : min(i, mm); for (int j = 0; j <= tem; j++) { double a = (input1[j] * tempinput2[i - j]); xx[i] += (input1[j] * tempinput2[i - j]); } } // set value to the output array for (int i = 0; i < mm + nn - 1; i++) output[i] = xx[i]; delete[] xx; } void gaussian_filter(COMPLEX *FD,int length,int frequence) { //double *gauss = new double[frequence]; //double *current_re = new double[frequence]; //double *data_out = new double[frequence]; for (int i = 0; i < length;i++) { if (i>length/2&&i<=length/2+frequence) { //gauss[i] = exp(-pow(length / 2 - i, 2) / (2 * frequence*frequence)); double H = exp(-pow(frequence - i, 2) / (2 * (length / 2)*(length / 2))); double M = (0.5 + 0.5*cos(2 * pi*(i - frequence) / (length / 2))); FD[i].re = FD[i].re*M; } } //convolution(current_re, gauss, data_out, length, length); //for (int i = 0; i < length;i++) //{ // FD[i].re = data_out[i]; //} //delete[] data_out; //delete[] current_re; //delete[] gauss; } void low_pass_filter(string path,int cut_frequence) { ifstream file_in; file_in.open(path);//輸入資料路徑 string lineStr; string str; int i = 0; double dv6[1 << POWER]; while (getline(file_in, lineStr)) { stringstream ss(lineStr); string str; int j = 0; double b[2]; while (getline(ss, str, ',')) { double a = atof(str.c_str()); b[j] = a; j++; } if (i == 1<<POWER) break; if (b[1] < -99) { b[1] = 0; } dv6[i] = b[1]; i++; } file_in.clear(); const int N = 1 << POWER; double data[N * 2] = { 0 }; COMPLEX *x = (COMPLEX*)malloc(sizeof(COMPLEX)* N); COMPLEX *y = (COMPLEX*)malloc(sizeof(COMPLEX)* N); cout << "原始值" << endl; for (int t = 0; t < 1 << POWER; t++) { x[t].re = dv6[t]; x[t].im = 0; cout << x[t].re << endl; } FFT(x, y, POWER); gaussian_filter(y, N, cut_frequence); IFFT(y, x, POWER); ofstream file_out; path = "./T_out.csv"; file_out.open(path, ios::out); float yy[N]; for (int i = 0; i < 1 << POWER; i++) { yy[i] = y[i].im; file_out << x[i].re << endl; } file_out.close(); } int _tmain(int argc, _TCHAR* argv[]) { int cut_frequence = 10000; string path = "./T.csv"; low_pass_filter(path, cut_frequence); return 0; }
下面也是一個低通濾波器,速度快一點
#include <stdio.h> #include <math.h> #include <iostream> #include <istream> #include <fstream> #include <sstream> #include <string> using namespace std; #define LENGTH 512 //w0=40時達到預期效果 /*-----------------------------------------------------------------// // Fast Fourier Transform program // //-----------------------------------------------------------------// // Algrithem: Cooley-Tukey Algrithem ( decimation in frequency ) // // // // xr : Real part of original data as the input; // // Real part of the output. // // xi : Imaginary part of original data as the input; // // Imaginary part of the output. // // nr : must be an positive integer, // // N=pow(2,nu) is the length of input array (points). // // T : =1.0 is forward transform; =-1.0 is reverse transform // // // //-----------------------------------------------------------------*/ void fft(float *xr, float *xi, int nr, float T) { int IBIT(int j, int m); int i, j, k, l, n, n2, nr1, i1, j1, k2, k1n2; float c, s, p, tr, ti, trc, tic, ars; n = (int)(pow(2.0, nr)); n2 = n / 2; nr1 = nr - 1; k = 0; for (i = 1; i <= nr; i++) { loop1: for (j = 1; j <= n2; j++) { k2 = k / (int)(pow(2.0, nr1)); p = (float)(IBIT(k2, nr)); ars = (float)(6.2831852*p / (float)(n)); //輻角 c = (float)(cos(ars)); s = (float)(sin(ars)); k1n2 = k + n2; tr = xr[k1n2] * c + xi[k1n2] * s*T; ti = xi[k1n2] * c - xr[k1n2] * s*T; xr[k1n2] = xr[k] - tr; xi[k1n2] = xi[k] - ti; xr[k] = xr[k] + tr; xi[k] = xi[k] + ti; k++; } k += n2; if (k<n) { goto loop1; } else { k = 0; nr1 = nr1 - 1; n2 /= 2; } } for (j = 1; j <= n; j++) { i = IBIT(j - 1, nr) + 1; if (i>j) { j1 = j - 1; i1 = i - 1; trc = xr[j1]; tic = xi[j1]; xr[j1] = xr[i1]; xi[j1] = xi[i1]; xr[i1] = trc; xi[i1] = tic; } } if (T<0.0) { for (j = 0; j <n; j++) { xr[j] /= n; xi[j] /= n; } } } int IBIT(int j, int m) { int i, it, j1, j2; it = 0; j1 = j; for (i = 1; i <= m; i++) { j2 = j1 / 2; it = it * 2 + (j1 - 2 * j2); j1 = j2; } return it; } /**************************************************************/ void read_csv(float *data,int length) { string path = "E:/Programs/MATLAB/T.csv"; ifstream file_in; file_in.open(path); string lineStr; string str; int i = 0; while (getline(file_in, lineStr)) { stringstream ss(lineStr); string str; int j = 0; double b[2]; while (getline(ss, str, ',')) { double a = atof(str.c_str()); b[j] = a; j++; } if (b[1] < -99) { b[1] = 0; } if (i<length) { data[i] = b[1]; } else { int a = 0; } i++; } file_in.clear(); } void main() { float xx[LENGTH], yy[LENGTH], h[LENGTH], w0, w1 = 5; int i, j; w0 = 10; read_csv(xx, LENGTH); //====================================// ofstream file; string path = "E:/Programs/MATLAB/T_out.csv"; file.open(path,ios::out); for (i = 0; i<LENGTH; i++) yy[i] = 0.0; for (i = 0; i<59; i++) { fft(xx, yy, 9, 1.0); //正向快速傅立葉變換求每道資料頻譜 for (j = 0; j<LENGTH; j++) //*窗函式 { if (j>w0&&j <= w0 + w1) { double aa = (0.54 + 0.46*cos(2 * 3.1415927*(j - w0) / w1)); xx[j] *= (0.54 + 0.46*cos(2 * 3.1415927*(j - w0) / w1)); yy[j] = 0.0; } else if (j>w0 + w1) yy[j] = xx[j] = 0.0; } for (j = 1; j<LENGTH; j++) //頻譜對稱逆向 { xx[LENGTH - j] = xx[j]; yy[LENGTH - j] = -yy[j]; } fft(xx, yy, 9, -1.0); //將濾波結果變換到時間與 //printf("第%d道資料處理成功\n", i + 1); } for (int i = 0; i < LENGTH;i++) { file << xx[i] << endl; } }