基于python与C++实现傅里叶变换(包含基于QT工程实现)学习过程记录
傅里叶变换的工程意义与目的
傅里叶变换python实现
傅里叶变换C++实现(基于QT)
傅里叶变换的工程意义与目的
近期工作中需要实现对动静脉的检测区分,通过对脉搏采集,进行傅里叶变换后,对脉冲周期性进行分析。傅里叶变换可以实现时域信号到频域信号的转换,将稍显杂乱且密集的时域信号转化为规律的频域信号,可以在频域坐标系下对周期性的信号进行筛选与处理。学习了很多相关代码,实现了想要的功能。
通过超声采集后得到的波形为超声多普勒信号如图:
通过傅里叶变换后可以得到频域下的图像如下:
傅里叶变换python实现
先使用python进行傅里叶变换的学习,找到了相关的代码进行学习。使用anaconda进行编程非常方便,有可以直接使用的fft函数,可以用来对傅里叶变换进行学习。先使用随机数生成一个随机曲线,再进行傅里叶变换,验证结果。python实现代码如下:
"""
Created on Wed Jan 6 10:44:00 2021
@author: 54969
"""
import numpy as np
from scipy.fftpack import fft,ifft
import matplotlib.pyplot as plt
# import seaborn
x=np.linspace(0,1,1001) 
# x=np.linspace(0,t,(Fs+1))
y=7*np.sin(2*np.pi*150*x) + 2.8*np.sin(2*np.pi*300*x)+5.1*np.sin(2*np.pi*550*x)
yy=fft(y) #快速傅里叶变换
yreal = yy.real # 获取实数部分
yimag = yy.imag # 获取虚数部分
yf=abs(fft(y)) # 取绝对值
xf = np.arange(len(y)) # 频率
plt.subplot(221)
plt.plot(x[0:50],y[0:50])
plt.title('Original wave')
plt.subplot(222)
plt.plot(xf,yf,'g')
plt.title('FFT of Mixed wave(two sides frequency range)',fontsize=7,color='#7A378B') #注意这里的颜色可以查询颜色代码表
plt.show()
运行结果如图:
傅里叶变换C++实现(基于QT)
通过python实现傅里叶变换,学习了傅里叶函数的变化过程,通过对采集样本进行complex变换,得到复数矩阵进行傅里叶计算。实部为时域坐标系的值,虚部为零进行傅里叶计算,得到变换后的实部与虚部求模绘制频域曲线,得到变换后的傅里叶曲线。在QT定义了一个按钮用于工程使用,C++代码如下:
void MainWindow::on_fft_PushButton_clicked()
{
qint16 PW[490]; //定义需要变换的数据容器,我的数据读取取消掉了
float Time[1];
QFile file("/home/zoey/Downloads/noise.txt"); //保存原始数据用于画图
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
cout << "Open failed." << endl;
}
for(int i = 0;i<490;i++)
{
QTextStream txtOutput(&file);
txtOutput << PW[i]<<endl ;
}
file.close();
Complex test[980] = {}; //定义复数矩阵
double a[490];
for (int j = 0; j < 490; j++)
{
test[j].real(PW[j]); //将需要变换的采样点放到矩阵实部
test[j].imag(0);
}
unsigned int N = 490, k = N, n;
double thetaT = 3.14159265358979323846264338328L / N; //定义pie/N
Complex phiT = Complex(cos(thetaT), -sin(thetaT)), T;
while (k > 1)
{
n = k;
k >>= 1; //补0,除以2
phiT = phiT * phiT;
T = Time[0];
for (unsigned int l = 0; l < k; l++)
{
for (unsigned int a = l; a < N; a += n)
{
unsigned int b = a + k;
Complex t = test[a] - test[b];
test[a] += test[b];
test[b] = t * T;
}
T *= phiT;
}
}
// 消项
unsigned int m = (unsigned int)log2(N);
for (unsigned int a = 0; a < N; a++)
{
unsigned int b = a;
// 反转位
b = (((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1));
b = (((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2));
b = (((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4));
b = (((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8));
b = ((b >> 16) | (b << 16)) >> (32 - m);
if (b > a)
{
Complex t = test[a];
test[a] = test[b];
test[b] = t;
}
}
Complex f = 1.0 / Time[0];
for (unsigned int i = 0; i < N; i++)
test[i] *= f;
//dft(data);
//std::cout << "dft" << std::endl;
for (int i = 0; i < 490; ++i)
{
cout<<"dft"<< test[i] << endl;
}
QFile file1("/home/zoey/Downloads/fft_noise1.txt"); //保存变换后的FFT数据用于画图
if(!file1.open(QIODevice::WriteOnly | QIODevice::Text))
{
cout << "Open failed." << endl;
}
for(int i = 0;i<490;i++)
{
QTextStream txtOutput(&file1);
txtOutput << test[i].imag()<<" "<<test[i].real()<<endl ;
}
file1.close();
得到变换前后的曲线如如图: