短时傅里叶变换函数编写

news2024/9/21 16:43:44

文章目录

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

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

在了解短时傅里叶变换之前,首先要知道是什么是傅里叶变换( 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-1
    xw = x(1+k*hop : wlen+k*hop).*win; %滑动窗口
    X = fft(xw,wlen); %离散傅里叶变换
    X = fftshift(X);  %将频率按顺序排列:负频率→直流→正频率
    X=abs(X)/wlen*2;  %将fft之后的幅度乘以N/2
    STFT(:,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)~=0
    nember = nember + 1;
end
Chirp = zeros(1,number);
for i = -fix(number/2):fix(number/2)-1
    Chirp(i+fix(number/2)+1)=exp(1j*(pi*(BandWidth/TimeWidth)*(i/Fs)^2));%产生复ChIrp信号
end
coeff = conj(fliplr(Chirp)); %把Chirp信号翻转并把复数共轭,产生脉压系数
%=========================================================================%
%                      绘制线性调频信号                                   %
%=========================================================================%
if plotEnableHigh == 1
    figure;
    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 == 1
    figure;
    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 == 1
    figure; %时域脉压结果
    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.coloradmin.cn/o/1238172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从 PUGC 到 SGC,普通店员也能用 AI 运营「粉丝群」

同一种文案风格反复使用,商品展示图也单调雷同,要直播时就直接「扔」个链接,社群、朋友圈这些品牌的私域重地有时极易被忽视,而变得千篇一律、简单粗暴。 但是,以内容驱动业务增长,已经成为越来越多品牌在做…

【EI会议征稿】第五届人工智能、网络与信息技术国际学术会议(AINIT 2024)

第五届人工智能、网络与信息技术国际学术会议(AINIT 2024) 2024 5th International Seminar on Artificial Intelligence, Networking and Information Technology 第五届人工智能、网络与信息技术国际学术会议(AINIT 2024)将于…

浅析教学型数控车床使用案例

教学型数控车床是一种专为教学和培训设计的机床,它具有小型化、高精度和灵活性的特点,可以作为学校和技术学院的培训机器。下面是一个使用案例,以展示教学型数控车床在教学实训中的应用。 案例背景: 某职业技术学院的机械工程专业…

Java计算时间差,距结束还有几天几小时几分钟

文章目录 1、写法2、备份3、LocalDate、LocalDateTime、Date、String互转 1、写法 //静态方法,传入年月日时分秒 LocalDateTime startTime LocalDateTime.of(2023, 11, 22, 15, 09, 59); LocalDateTime endTime LocalDateTime.of(2023, 11, 30, 0, 0, 0); //计算…

2023.11.22 -数据仓库

目录 https://blog.csdn.net/m0_49956154/article/details/134320307?spm1001.2014.3001.5501 1经典传统数仓架构 2离线大数据数仓架构 3数据仓库三层 数据运营层,源数据层(ODS)(Operational Data Store) 数据仓库层&#…

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

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

程序的执行原理(下)

文章目录 系统的硬件组成总线I/0设备主存处理器程序计数器(PC)加载:存储:操作:跳转: 运行 hello 程序读入寄存器,再把它存放到内存从磁盘加载程序到主存处理器执行程序并显示 参考 系统的硬件组成 总线 贯穿整个系统的是一组电子管道&#…

Java爬虫框架下代理使用中的TCP连接池问题及解决方案

引言 当使用Java爬虫框架进行代理爬取时,可能会遇到TCP连接池问题,导致"java.net.BindException: Cannot assign requested address"等错误。本文将介绍如何以爬取小红书为案例,解决Java爬虫框架中代理使用中的TCP连接池问题&…

连线鑫云:企业级存储设备制造商!

我们在今年的双11专场直播中,有幸邀请到了鑫云存储的嘉宾与我们连线,为大家作了一场精彩的分享。 这里,首先感谢鑫云存储对水经注的大力支持! 现在,我们将嘉宾分享的内容进行简单整理,并以图文的方式与大家…

如何隐藏自己的代码(很酷)

1.引入 幻想当我们成为一名优秀的程序员,有着各大公司想要买我们的代码,但我们并不想要让他们知道我们代码的实现,毕竟一复制便可以解决,这里我们希望有一种方法可以把我们的核心代码给隐藏掉,那我们又应该怎么去实现呢…

计算3个点的6种分布在平面上的占比

假设平面的尺寸是6*6,用11的方式构造2,在用21的方式构造3 2 2 2 1 2 2 2 2 2 1 2 2 2 2 2 1 2 2 3 3 3 x 3 3 2 2 2 1 2 2 2 2 2 1 2 2 在平面上有一个点x,11的操作吧平面分成了3部分2a1,2a…

【鸿蒙应用ArkTS开发系列】- 云开发入门实战二 实现城市多级联动Demo(上)

目录 概述 云数据库开发 一、创建云数据库的对象类型。 二、预置数据(为对象类型添加数据条目)。 三、部署云数据库 云函数实现业务逻辑 一、创建云函数 二、云函数目录讲解 三、创建resources目录 四、获取云端凭据 五、导出之前创建的元数据…

笔记58:Encoder-Decoder 架构

本地笔记地址:D:\work_file\(4)DeepLearning_Learning\03_个人笔记\3.循环神经网络\第9章:动手学深度学习~现代循环神经网络 a a a a a a a a a

我在Vscode学OpenCV 几何变换(缩放、翻转、仿射变换、透视、重映射)

几何变换指的是将一幅图像映射到另一幅图像内的操作。 cv2.warpAffine:使用仿射变换矩阵对图像进行变换,可以实现平移、缩放和旋转等操作。cv2.warpPerspective:使用透视变换矩阵对图像进行透视变换,可以实现镜头校正、图像纠偏等…

单链表相关面试题--3.链表的中间节点

3.链表的中间节点 876. 链表的中间结点 - 力扣(LeetCode) /* 解题思路: 通过快慢指针找到中间节点,快指针每次走两步,慢指针每次走一步,当快指针走到结尾的时候,慢指针正好走到中间位置 */ typ…

【点云上采样】最近邻插值上采样算法

文章目录 声明简介代码 声明 本帖更新中 简介 点云最近邻插值上采样算法是一种常见的点云处理方法,用于将稀疏的点云数据进行上采样,增加点云的密度和细节。该算法基于最近邻的原理,在已有的点云数据中找到最近邻的点,并根据其…

psutil - Python中用于进程和系统监控的跨平台库

1、简介 psutil(进程和系统实用程序)是一个跨平台库,用于检索 Python 中运行的进程和系统利用率(CPU、内存、磁盘、网络、传感器)的信息。 它主要用于系统监控、分析和限制进程资源以及管理正在运行的进程。 它实现…

Positive证书:最便宜的SSL证书

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

数字IC基础:有符号数和无符号数加、减法的Verilog设计

相关阅读 数字IC基础https://blog.csdn.net/weixin_45791458/category_12365795.html?spm1001.2014.3001.5482 本文是对数字IC基础:有符号数和无符号数的加减运算一文中的谈到的有符号数加减法的算法进行Verilog实现,有关算法细节请阅读原文&#xff0…

设计一个实用好看的餐边柜或者酒柜需要知道这5点。福州中宅装饰,福州装修

餐厅旁边的餐边柜和酒柜是提升餐厅功能性和美观度的重要元素。它们不仅可以提供额外的储物空间,还可以展示精美的餐具和收纳酒品。下面为大家分享一些布置餐边柜和酒柜的灵感,让你的餐厅更加时尚和实用。 1. 餐边柜与酒柜的组合 将餐边柜和酒柜组合在一…