短时傅里叶变换函数编写

文章目录

      • 傅里叶变换与短时傅里叶变换
      • 什么是窗?
      • 自己对手实现短时傅里叶变换

傅里叶变换与短时傅里叶变换

在了解短时傅里叶变换之前,首先要知道是什么是傅里叶变换( fourier transformation,FT),傅里叶变换就是将一个信号分解为不同频率的复指数信号的和,例如我们要对一段钢琴曲进行傅里叶变换,它的结果能够告诉我们这一段时间内按下了那些琴键(简单假设为不同琴键对应不同频率的声音),注意我们处理的时长是整个时间段。傅里叶变换的公式可由下面给出:
F ( ω ) = F [ s ( t ) ] = ∫ − ∞ + ∞ s ( t ) e − j ω t d t F(\omega)=\mathcal{F}[s(t)]=\int_{-\infty}^{+\infty} s(t)e^{-j\omega t}dt F(ω)=F[s(t)]=+s(t)etdt
可以看出来,傅里叶变换得到的是一个谱,它是不同频率下对应的幅度谱和相位谱,幅度谱我们用的比较多。利用傅里叶变换能够对信号
进行分析。根据信号是否为周期信号,以及时域上是否连续,又可以分为傅里叶级数展开、离散时间傅里叶变换、离散傅里叶变换等等,在此不再赘述,《信号与系统》和《数字信号处理》的相关书籍介绍很多。
下面是短时傅里叶变换,(short-time fourier transformation,STFT),有时候也叫加窗傅里叶变换,时间窗口使得信号只在某一小区间内有效,这就避免了传统的傅里叶变换在时频局部表达能力上的不足,使得傅里叶变化有了局部定位能力。公式如下:
Ω ( t , f ) = Γ [ s ( t ) ] = ∫ − ∞ + ∞ s ( τ ) ω ( τ − t ) e − j 2 π f τ d τ \Omega(t,f)=\Gamma[s(t)]=\int_{-\infty}^{+\infty} s(\tau)\omega (\tau-t)e^{-j2\pi f \tau }d\tau Ω(t,f)=Γ[s(t)]=+s(τ)ω(τt)ej2πfτdτ
还是以钢琴音乐的信号分析,虽然傅里叶变换能够告诉我们这段音乐中包含那些琴键的声音,但是我们无法知道是在哪些时间点按下这些琴键的。傅里叶变换是一种频域分析共工具,而短时傅里叶变换就是为了解决以上问题而提出的一种时频域方法,后面还有人提出了小波变换。
mailab中可以采用stft函数和spectrogram函数来实现,当然也可以自己动手实现。

什么是窗?

在信号处理中,我们经常听到海明窗(hamming window)、汉宁窗(hanning window)之类的名字,这是什么意思呢?简单来说,窗就是一个函数,它的形状像窗,所以类似的函数都叫窗。
例如我们处理的语音信号一般在10ms到30ms之间,我们可以把它看成是平稳的。为了处理语音信号,我们要对语音信号进行加窗,也就是一次仅处理窗中的数据。因为实际的语音信号是很长的,我们不能也不必对非常长的数据进行一次性处理。明智的解决办法就是每次取一段数据,进行分析,然后再取下一段数据,再进行分析。
怎么仅取一段数据呢,一种方式就是构造一个函数。这个函数在某一区间有非零值,而在其余区间皆为0。汉明窗就是这样的一种函数。它主要部分的形状像 s i n ( x ) sin(x) sin(x)在0到 π \pi π区间的形状,而其余部分都是0,这样的函数乘上其他任何一个函数 f ( x ) f(x) f(x) f ( x ) f(x) f(x)只有一部分有非零值。
为什么海明窗这样取呢,因为之后我们会对海明窗中的数据进行FFT,它假设一个窗内的信号是代表一个周期的信号。(也就是说窗的左端和右端应该大致能连在一起)而通常一小段音频数据没有明显的周期性,加上汉明窗后,数据形状就有点周期的感觉了。
因为加上海明窗,只有中间的数据体现出来了,两边的数据信息丢失了,所以等会移窗的时候,只会移1/3或1/2窗,这样被前一帧或二帧丢失的数据又重新得到了体现。
在matlab中可以借助函数很轻松的生成窗,例如我们要创建一个长度为64点的汉宁窗

L = 64;
wvtool(hann(L))

在这里插入图片描述

自己对手实现短时傅里叶变换

这里参考了知乎笔记matlab短时傅里叶变换
自定义函数如下:

function [STFT, f, t] = mystft(x, win, hop, fs)
% 该函数用于短时傅里叶变换
%  Author:huasir 2023.11.22 @Beijing
% Input : 
%   * x: 输入信号
%   * win:窗,可以采用汉宁窗
%   * hop:窗口滑动的步长,可以为1
%   * fs:采样频率,由输入信号的采样率决定
% Output : 
%    * STFT:短时傅里叶变换的结果,每一列代表某一个窗口下的fft结果,只保留了幅度谱
%    * f: 频率坐标
%    * t: 时间坐标
x = reshape(x,length(x),1); %将向量转为列向量,与后续的点乘相对应
xlen = length(x);%信号长度
wlen = length(win);%窗长度
L = 1+fix((xlen-wlen)/hop);%窗口数目
STFT = zeros(wlen,L);%返回空矩阵
%循环进行傅里叶变换
for k = 0:L-1xw = x(1+k*hop : wlen+k*hop).*win; %滑动窗口X = fft(xw,wlen); %离散傅里叶变换X = fftshift(X);  %将频率按顺序排列:负频率→直流→正频率X=abs(X)/wlen*2;  %将fft之后的幅度乘以N/2STFT(:,1+k) = X;  %存储
end
%频率坐标
f=linspace(-fs/2,fs/2,wlen);
%时间坐标
t = (wlen/2:hop:wlen/2+(L-1)*hop)/fs;%秒
end

以线性调频信号为例,下面是采用这个自定义函数进行短时傅里叶变换并绘制时频图的代码:

%% 对LFM信号进行短时傅里叶变换
% 主要内容:线性调频信号的生成、雷达回波的模拟、对雷达回波进行短时傅里叶变换
% 短时傅里叶变换采用的是自定义函数
% Author: zhenhualiu 2023.11.22
%=========================================================================%
%                        雷达参数设置                                     %
%=========================================================================%
clear all;close all;clc;
BandWidth = 2.0e6;  %雷达发射信号带宽,带宽=B=1/tau,tau是脉冲宽度
TimeWidth = 40.0e-6; %雷达发射信号的脉冲时宽
PRT = 100e-6;       %雷达发射脉冲重复周期(s),100us对应1/2*100*300=15000米最大无模糊距离
Fs = 4.0e6;         %采样频率
NoisePower = -12;   %噪声功率
SigPower = 1;           %目标功率,无量纲
TargetDistance = 2000;  %目标距离,单位:m,相对于的距离门DelayNumber = fix(Fs*2*TargetDistance/C); %把目标距离换算成采样点(距离门)
plotEnableHigh = 1; %绘图控制符
%=========================================================================%
%             调用函数产生线性调频信号、雷达回波和脉压系数                %
%=========================================================================%
[LFMPulse,targetEchoPRT,matchedFilterCoeff,pulseNumber,PRTNumber] = GenerateLFMSignal(BandWidth,TimeWidth,PRT,Fs,SigPower,TargetDistance,plotEnableHigh);%调用函数
%=========================================================================%
%=========================================================================%
%                  设置窗、步长并进行短时傅里叶变换                       %
%=========================================================================%
wlen=32;%设置窗口长度。窗口越长时间分辨率越差,频率分辨率越好。
hop = 1; %每次平移的步长,最小为1。越小图像时间精度越好,但计算量大。
win = hanning(wlen, 'periodic');%窗函数
figure; %绘制汉宁窗
plot(win);title('汉宁窗');
[S2, f1, t1] = mystft(targetEchoPRT, win, hop, Fs); %采用自定义函数进行短时傅里叶变换
%=========================================================================%
%                     绘制短时傅里叶变换的伪彩色图                        %
%=========================================================================%
figure;
Figure=pcolor(t1,f1,S2); %绘制伪彩色图
colormap('jet'); %指定色系:parula、turbo、jet等等
shading flat;%将每个网格片用同一个颜色进行着色,且网格线也用相应的颜色,从而使得图形表面显得更加光滑。
shading interp;%在网格片内采用颜色插值处理,得出的表面图显得最光滑。
colorbar; %显示图像的颜色条,提供对图像彩色的可视化表示,使得用户能够更直观的理解图像数据的分布和范围

其中生成线性调频信号的函数如下:

function [LFMPulse,targetEchoPRT,matchedFilterCoeff,pulseNumber,PRTNumber] = GenerateLFMSignal(bandWidth,pulseDuration,PRTDuration,samplingFrequency,signalPower,targetDistece,plotEnableHigh)
% 该函数用于产生线性调频信号,以及雷达的目标反射回波,仅产生单个回波
%  Author:huasir 2023.9.21 @Beijing
% Input : 
%   * bandWidth: 信号带宽 ,参考值:2.0e6 表示2MHz
%   * pulseDuration:脉冲持续时间,参考值:40.0e-6 表示40ms
%   * PRTDuration:脉冲重复周期,参考值:240ms
%   * samplingFrequency:采样频率,参考值:2倍的信号带宽
%   * signalPower:信号能量,参考值:1
%   * targetDistece:目标距离,最大无模糊距离由脉冲重复周期决定。计算公式:1/2*PRTDuration*光速
%   * plotEnableHigh: 绘图控制符,1:打开绘图,0:关闭绘图
% Output : 
%    * LFMPulse:线性调频信号
%    * targetEchoPRT: 目标反射回波
%    * matchedFilterCoeff: 匹配滤波器系数
%    * pulseNumber:当前采样率下线性调频信号的采样点数
%    * PRTNumber:1个PRT对应的采样点数
C = 3.0e8;      %光速(m/s)
BandWidth = bandWidth;  %雷达发射信号带宽,带宽=B=1/tau,tau是脉冲宽度
TimeWidth = pulseDuration; %雷达发射信号的脉冲时宽PRT = PRTDuration;       %雷达发射脉冲重复周期(s),240us对应1/2*240*300=360000米最大无模糊距离
Fs = samplingFrequency;         %采样频率
SampleNumber = fix(Fs*PRT);
%=========================================================================%
%                        目标参数设置                                     %
%=========================================================================%
SigPower = signalPower;           %目标功率,无量纲
TargetDistance = targetDistece; %目标距离,单位:m
DelayNumber = fix(Fs*2*TargetDistance/C); %把目标距离换算成采样点(距离门)
%=========================================================================%
%                        产生线性调频信号、匹配滤波器                     %
%=========================================================================%
number = fix(Fs*TimeWidth); %回波采样点数=脉压系数长度=暂态点数目+1
if rem(number,2)~=0nember = nember + 1;
end
Chirp = zeros(1,number);
for i = -fix(number/2):fix(number/2)-1Chirp(i+fix(number/2)+1)=exp(1j*(pi*(BandWidth/TimeWidth)*(i/Fs)^2));%产生复ChIrp信号
end
coeff = conj(fliplr(Chirp)); %把Chirp信号翻转并把复数共轭,产生脉压系数
%=========================================================================%
%                      绘制线性调频信号                                   %
%=========================================================================%
if plotEnableHigh == 1figure;plot(real(Chirp)); %绘制线性调频信号xlabel('Sampling points'); ylabel('Amplitude');title('线性调频信号实部');
end
SignalTemp = zeros(1,SampleNumber); %1个PRT
SignalTemp(DelayNumber+1:DelayNumber+number) = sqrt(SigPower)*Chirp;%将线性调频信号按照距离进行延时
if plotEnableHigh == 1figure;plot(real(SignalTemp)); %绘制1个完整的PRT的雷达回波信号xlabel('Range bin'); ylabel('Amplitude');title('雷达回波的实部');
end
%=========================================================================%
%                          进行脉冲压缩                                   %
%=========================================================================%
Echo = SignalTemp; % 目标回波
pc_time0 = conv(Echo,coeff); % 回波和滤波器卷积的结果
pc_time1 = pc_time0(number:number+SampleNumber-1); %去掉暂态点
realTargetRange = find(abs(pc_time1)==max(abs(pc_time1)))-1; %由脉压结果目标距离
fprintf('The target range bin is  %d',realTargetRange);
if plotEnableHigh == 1figure; %时域脉压结果subplot(2,1,1);plot(abs(pc_time0),'r-');xlabel('Range bin'); ylabel('Amplitude');title('时域脉压结果');subplot(2,1,2);plot(abs(pc_time1),'r-');xlabel('Range bin'); ylabel('Amplitude');title('去掉暂态点的时域脉压结果');
end
%=========================================================================%
%                              返回参数                                   %
%=========================================================================%
LFMPulse = Chirp; %线性调频信号
targetEchoPRT = SignalTemp; %目标反射回波
matchedFilterCoeff = coeff; %匹配滤波器系数
pulseNumber = number; %线性调频信号(仅脉内)的采样点数
PRTNumber = SampleNumber; %目标反射回波(整个PRT)的采样点数
end

绘制的线性调频信号的时域图和时频图如下:
在这里插入图片描述

图1. 线性调频信号时域图

在这里插入图片描述

图2. 线性调频信号时频域图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/206113.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网上找客户有什么渠道?

在数字化时代,企业和个体创业者需要善于利用互联网来拓展业务和寻找潜在客户。网上找客户的渠道多种多样,合理运用这些渠道可以极大地提高曝光和业务机会。以下是一些成功寻找客户的网上渠道: 1. 社交媒体平台 社交媒体已成为建立专业形象和…

使用Microsoft Dynamics AX 2012 - 4. 销售和配送

销售和分销的主要职责是为客户提供您的商品和服务。为了完成这项任务,销售和分销需要通过分拣、运输和开具发票来处理销售订单,从而管理客户的材料需求。 销售和配送业务流程 在我们开始详细介绍之前,下面几行概述了销售和配送中的业务流程…

想打造私域流量帝国?先解决这4个难题!

一、谁是你的目标用户 1. 清晰界定目标用户:确定你的产品或服务主要面向的用户群体,如年龄段、性别、职业等特征。 2. 确定最有购买力的用户群体:分析哪个用户群体在购买你的产品或服务时更容易乐于支付,并将其作为重点关注对象。…

【考研】数据结构(更新到双链表)

声明&#xff1a;所有代码都可以运行&#xff0c;可以直接粘贴运行&#xff08;只有库函数没有声明&#xff09; 线性表的定义和基本操作 基本操作 定义 静态&#xff1a; #include<stdio.h> #include<stdlib.h>#define MaxSize 10//静态 typedef struct{int d…

【性能测试学习】2023最有效的7大性能测试技术(建议收藏)

进入互联网时代&#xff0c;性能测试显得越来越重要&#xff0c;移动应用、web应用和物联网应用都需要进行性能测试和性能调优&#xff0c;而进行性能和负载测试会产生了大量的数据&#xff0c;这些数据难以分析。除了数据分析&#xff0c;我们还会遇到其它一些困难和挑战。 今…

新手做抖店,这6点建议一定要收好,能让你不亏钱!

我是电商珠珠 我呢&#xff0c;目前身居郑州。 电商这个行业也做了5年多了&#xff0c;抖店从20年开始做&#xff0c;到现在也已经快3年了。 其实&#xff0c;我做抖店期间呢&#xff0c;踩过很多坑&#xff0c;所以今天就把我所踩过的坑&#xff0c;给做抖店的新手总结了6点…

PCB抄板的一些方法

PCB抄板的技术实现过程简单来说&#xff0c;就是先将要抄板的电路板进行扫描&#xff0c;记录详细的元器件位置&#xff0c;然后将元器件拆下来做成物料清单&#xff08;BOM&#xff09;并安排物料采购&#xff0c;空板则扫描成图片经抄板软件处理还原成pcb板图文件&#xff0c…

C语言中的多线程调用

功能 开启一个线程&#xff0c;不断打印传进去的参数&#xff0c;并且每次打印后自增1 代码 #include<windows.h> #include<pthread.h> #include<stdio.h>void* print(void *a) {int *ic(int*)a;float *fc(float*)(asizeof(int)*2);double *dc(double*)(as…

解析IBM SPSS Statistics 26 forMac/win中文版:全面统计分析解决方案

作为一款强大的统计分析软件&#xff0c;IBM SPSS Statistics 26&#xff08;spss统计软件&#xff09;在全球范围内被广泛使用。无论是学术研究、市场调研还是商业决策&#xff0c;SPSS统计软件都能提供全面的解决方案&#xff0c;帮助用户快速、准确地分析数据。 首先&#…

内容输入.type

内容输入.type 查看完整说明 语法 .type(text) .type(text, options)正确用法 cy.get(input).type(Hello, World) // Type Hello, World into the input错误用法 cy.type(Welcome) // Errors, cannot be chained off cy cy.clock().type(www.cypress.io) // Errors, clock…

Positive证书:最便宜的SSL证书

在当今数字化的时代&#xff0c;网上交易和信息传输已经成为我们生活中不可或缺的一部分。然而&#xff0c;随着网络犯罪的增加&#xff0c;确保在线信息的安全性变得尤为重要。Positive证书作为一种经济实惠的数字证书&#xff0c;在提供有效安全性的同时&#xff0c;为用户提…

Android修行手册-POI操作Excel文档

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…