python的opencv操作记录(七)——短时傅里叶变换(stft)

article/2025/10/7 7:17:03

文章目录

  • DCT-傅立叶变换的局限性
  • STFT 短时傅里叶变换
    • 从另一个角度来理解图像的“时域”数据
      • 看看fs和t这两个参数
      • 再看看怎么划分窗口
      • 最后看另外两个出参
      • Zxx返回结构
  • 图像的stft

DCT-傅立叶变换的局限性

接上一篇DCT的文章,DCT只提取了整个信号域的频率信息,但是没有时间信息,或者说没有位置信息,也就是说不知道这个频率是发生在哪个位置。
如果在图像处理的语境下的话,那就是不知道这个像素变换发生在什么位置。
我们来写段代码作一个实验:

    img1 = np.zeros((100, 100, 3), dtype="uint8")cv2.rectangle(img1, (60, 20), (70, 70), (255, 255, 255), 1)cv2.rectangle(img1, (80, 20), (90, 70), (255, 255, 255), 1)img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)dft1 = cv2.dft(np.float32(img1), flags=cv2.DFT_COMPLEX_OUTPUT)print(dft1)cv2.imshow("img_ori1", img1)img2 = np.zeros((100, 100, 3), dtype="uint8")cv2.rectangle(img2, (20, 20), (30, 70), (255, 255, 255), 1)cv2.rectangle(img2, (40, 20), (50, 70), (255, 255, 255), 1)img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)dft2 = cv2.dft(np.float32(img2), flags=cv2.DFT_COMPLEX_OUTPUT)print(dft2)cv2.imshow("img_ori2", img2)

图像显示如下:
在这里插入图片描述

两个dft的输出结果一模一样,都是下面的一串:
[[[ 6.1200000e+04 0.0000000e+00]
[ 0.0000000e+00 4.7354695e+04]
[-1.5694755e+04 -1.2207031e-04]

[ 1.1026633e-03 -1.1961035e+04]
[-1.5694755e+04 1.2207031e-04]
[ 0.0000000e+00 -4.7354695e+04]]

从上面的这个小实验就可以看出来,两个方框造成的图像像素值变换的频率是一样的,但是出现的位置是不一样的,但是在普通的dft中无法得出(前一篇文章中提到,dft的两个维度,一个是频率,另外一个是像素值,但是没有出现的位置)

STFT 短时傅里叶变换

所谓的“短时”,就是把整个信号域划分成一个一个的小段,就可以得到每一个段的频率和相位谱,再加上每个时间窗这个“时间”维度,就知道了这个“位置-信号中的位置”数据了。当然,还有一个好处就是,可以细分一个时间窗口到某一个稳定信号变换域,就不会受频率变换的影响了。

这里面有任何一个滑动窗口函数涉及到的问题,就是这个窗口到底划多宽合适。同样,写点代码来试试看。

代码是用的python中的scipy框架库里的signal子库:

  scipy.signal.stft(x,fs = 1.0,window =‘hann’,nperseg = 256,noverlap = None,nfft = None,detrend = False,return_oneside = True,boundary =‘zeros’,padded = True,axis = -1
  • 输入参数

    • x: STFT变换的时域信号
    • fs: 时域信号的采样频率
    • window: 时域信号分割需要的窗函数,可以自定义窗函数(但是这个方面没有尝试,需要自定义的话请自己尝试)
    • nperseg: 窗函数长度
    • noverlap: 窗函数重叠数,默认为50%。
    • nfft: FFT的长度,默认为nperseg。如大于nperseg会自动进行零填充
    • return_oneside : True返回复数实部,None返回复数。
      剩下的参数一般不会涉及,采用默认的参数。
  • 输出参数

    • f: 频率
    • t: 时间
    • Zxx: STFT时频数据

从另一个角度来理解图像的“时域”数据

我在网上找了很多资料,都没有解释上面几个入参和出参的具体物理含义,也就是这些参数在整个变换过程中起到了什么作用。所以我就先从简单一维数组信号开始作实验,来仔细说说这些参数到底代表什么含义。

看看fs和t这两个参数

一段最基本的代码,在这段代码中,信号就是一个直流信号,没有任何变化。

x = [1, 1, 1, 1]
fs = 1f, t, Zxx = signal.stft(x, fs, nperseg=1)

我们来看一下输出:
在这里插入图片描述

首先来看一下这个fs这个入参和t这个出参。

还是把x这个信号看成是一个完整信号的采样结果,代码中的[1, 1, 1, 1]就是对这个信号采样结果,我们这个例子中的 fs = 1,表示这一个数据表示一个信号周期,而t这个出参就是这四个数据是在第几个时间周期内。

如果fs=1,那么上面就是4个周期:1,2,3,4;
如果fs=2,那么上面就是2个周期:1,2。因为每个周期里面有两次采样,也就是采样频率是2;
以此类推

我们改一下参数fs试试看上面的这段描述。

x = [1, 1, 1, 1]
fs = 2f, t, Zxx = signal.stft(x, fs, nperseg=1)

在这里插入图片描述

在这个demo中,因为采样频率为2,所以总共才两个周期,4个数据也就是总共4个采样点,分布在2个信号周期内,t就变成[0, 0.5, 1, 1.5]了。

再看看怎么划分窗口

stft对dft的最大的改进就是对信号进行了窗口的划分,对每个窗口内的“短时”信号进行单独的dft变换。
控制窗口的主要由两个参数来控制:
nperseg:表示多少个采样点来组成一个窗口。
noverlap:表示窗口与窗口之间有多少个采样点重合,默认值就是nperseg / 2,这里要做整除。

窗口输出后,同样会在出参t上体现。

x = [1, 1, 1, 1, 1, 1, 1, 1]
fs = 1f, t, Zxx = signal.stft(x, fs, nperseg=4)

在这里插入图片描述

我理解,t这个出参实际上是记录了每个窗口的起始周期(时间维度),那么在这个小demo中,总共分成了4个窗口,共5个轴(axis,5个线形成4个区段,每个轴就是一个时间点)。这是因为窗口与窗口之间必须有2个采样点的重合,所以5个轴的时间点就是0, 2, 4, 6, 8。

为什么说是其实周期呢,我们把fs改成2试一下。

x = [1, 1, 1, 1, 1, 1, 1, 1]
fs = 2f, t, Zxx = signal.stft(x, fs, nperseg=4)

t的输出结果就变成了[0. 1. 2. 3. 4.],因为2个采样点在一个周期内,所以结果就是原来的一半。

另外,如果分窗的时候不能整除,那么剩下的采样点部分就需要进行补充。
补充的规则由另外两个参数来确定:

scipy官网上的描述如下:

  • boundarystr or None, optional
    Specifies whether the input signal is extended at both ends, and how to generate the new values, in order to center the first windowed segment on the first input point. This has the benefit of enabling reconstruction of the first input point when the employed window function starts at zero. Valid options are [‘even’, ‘odd’, ‘constant’, ‘zeros’, None]. Defaults to ‘zeros’, for zero padding extension. I.e. [1, 2, 3, 4] is extended to [0, 1, 2, 3, 4, 0] for nperseg=3.

  • paddedbool, optional
    Specifies whether the input signal is zero-padded at the end to make the signal fit exactly into an integer number of window segments, so that all of the signal is included in the output. Defaults to True. Padding occurs after boundary extension, if boundary is not None, and padded is True, as is the default.

另外,补充边缘还需要满足下列的条件。

  • In order to enable inversion of an STFT via the inverse STFT in istft, the signal windowing must obey the constraint of “Nonzero OverLap Add” (NOLA), and the input signal must have complete windowing coverage (i.e. (x.shape[axis] - nperseg) % (nperseg-noverlap) == 0). The padded argument may be used to accomplish this.

最后看另外两个出参

以下面这demo为例:

x = [1, 1, 1, 1, 1, 1, 1, 1]
fs = 1f, t, Zxx = signal.stft(x, fs, nperseg=4)

先看下t,这个数组上面说到了,这就是多少个时间窗,这个例子中就是:
[0. 2. 4. 6. 8.]
表示总共有5个时间窗。

先看看频率,在signal的库中,f是一个数组,我自己的理解,这里的频率是指一个时间周期内的样本梯度。

输出的f为:
[0. 0.25 0.5 ],这表示总共有三种频率。我们拆开了看这个过程:
nperseg = 4的话,那么overlap就等于2,上面看到了总共是5个时间窗,那么我理解补充完边界的结构是:
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
时间窗就是:
[0, 0, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1]
[1, 0, 0, 0]

上面几个时间窗中的样本梯度分布就是:0.5,0.25,0

Zxx返回结构

Zxx结构就是一个二维数组:
[[ 0.75+0.j 1. +0.j 1. +0.j 1. +0.j 0.25+0.j ]
[-0.5 +0.25j -0.5 +0.j -0.5 +0.j -0.5 +0.j 0. -0.25j]
[ 0.25+0.j 0. +0.j 0. +0.j 0. +0.j -0.25+0.j ]]

横着的就是时间窗,竖着的就是梯度分布。

plt.pcolormesh(t, f, np.abs(Zxx), vmin=0, vmax=amp, shading='gouraud')plt.title('STFT Magnitude')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()

使用上面的代码就可以画出一个时域-频域的分布图。每个交叉点上就是Zxx二维数组中的频率+相位的值。
在这里插入图片描述

图像的stft

图像是个二维数据,而上面的过程的输入都是一个一维数组,二维数组的是stft是对每行数据作一次stft,然后保存在zxx数据结构中。

# 分别作stft
f1, t1, Zxx1 = signal.stft(img1, fs=1, nperseg=100)
f2, t2, Zxx2 = signal.stft(img2, fs=1, nperseg=100)# 第二十行有区别
plt.pcolormesh(t1, f1, np.abs(Zxx2[20]), vmin=0, vmax=200, shading='gouraud')plt.pcolormesh(t2, f2, np.abs(Zxx2[20]), vmin=0, vmax=200, shading='gouraud')

结果如下:
在这里插入图片描述
在这里插入图片描述

从分布上就能看出来,stft可以按照窗口来区分不同的频率,从而达到区分两者的目的。


http://chatgpt.dhexx.cn/article/O12BCAmr.shtml

相关文章

傅里叶变换@(stft和istft)

一、窗函数之短时傅里叶变换stft 前提: 傅里叶变换是针对平稳信号的,但是很多实际应用中的信号都是非平稳的,如果要计算其傅里叶变换,需要假设其周期无限长,然后对这个无限长的信号做变换分析。但是这种无限长信号分…

scipy短时傅里叶分析STFT

scipy短时傅里叶分析 基本原理: 为了使STFT能够通过STFT逆变换反变换,信号加窗必须服从“非零重叠加”(NOLA)的约束,输入信号必须具有完整的加窗覆盖即 ( x . s h a p e [ a x i s ] − n p e r s e g ) (x.shape[axis] - nperseg) % (nper…

STFT笔记

因为不懂这个被鄙视了,调包侠来补作业。 基础知识 FFT(fast fourier transfrom)快速傅里叶变换。 推荐阅读《深入浅出的讲解傅里叶变换(真正的通俗易懂)》, 《梅尔频率倒谱系数(MFCC)》。 频谱只获得了频…

利用短时傅里叶变换(STFT)对信号进行时频谱分析和去噪声

利用短时傅里叶变换(STFT)对信号进行时频谱分析和去噪声 1、背景 傅里叶变换(TF)对频谱的描绘是“全局性”的,不能反映时间维度局部区域上的特征,人们虽然从傅立叶变换能清楚地看到一整段信号包含的每一个频率的分量值…

STFT(短时傅里叶变换)音频特征提取,用于语音识别 python

在各种音频相关的任务中,不管用什么模型或网络,得到所需的音频特征肯定是必要的一步。下面简单说一下STFT特征 一、原始信号 在说STFT之前,先说一下读入的原始信号,图像是在XY二维上描述的像素点的集合,相应的&#x…

STFT原理及MATLAB代码

原文地址:http://blog.csdn.net/shengzhadon/article/details/46811923 一、先说说STFT的理论 1.概念和特点 STFT(short-time Fourier transform,短时傅里叶变换)是和傅里叶变换相关的一种数学变换,用以确定时变信号其…

nvme分区选mbr还是guid_win7安装系统硬盘模式mbr和guid选哪个?

有很多系统之家的用户,还是喜欢安装win7系统的。但是在新的硬盘里面我们要分区的话,会出现mbr和guid是硬盘分区的两个格式,很多用户在做系统的时候不知道选哪个好,其实最好根据自己的电脑的配置,下面来看看详细的介绍吧…

uefi+guid分区与legacy+mbr分区_硬盘分区表格式GUID和MBR知识普及

我们的电脑硬盘分区格式一共有两种,一种是GUID(GPT),一种是MBR。 啥是硬盘分区呢?举个例子你就明白了,很多人去买电脑的时候,比如你买的电脑只有一块硬盘,店家就会给你分区,把这一块硬盘分成好几个区,比如分成了系统,软件,文档这样三个,那么你打开【我的电脑】后就会…

nvme分区选mbr还是guid_SSD里的特例:NVME固态改MBR格式、装Win7

问题一:NVME固态是否支持MBR文件格式: 场景:前几天朋友兴致冲冲的买了个建兴T10,准备好好体验一下。但是正当他吃着火锅,唱着歌,突然就给麻匪劫了——电脑系统竟然接二连三莫名奇妙的崩溃。 于是朋友就向我求助。由于他的电脑最近除了换了硬盘,并没有添加任何其他的硬设…

guid备份分区表crc错误_硬盘GPT和MBR分区表转换方法

随着硬盘容量越来越大,传统的MBR硬盘分区模式已经不能满足发展需要,预装win8或win10系统的硬盘默认都是GPT分区表(GUID格式),GPT识别2T以上的硬盘以及UEFI启动模式。不过在对系统进行重装时,经常会遇到无法安装在GPT或MBR硬盘中的问题,那么这个时候就需要对硬盘的分区表进…

GUID与MBR

磁盘分区表方案 全局唯一标识分区表是一个实体硬盘的分区表的结构布局的标准。 先说说目前广泛使用的磁盘分区表方案。传统的分区方案(称为MBR分区方案)是将分区信息保存到磁盘的第一个扇区(MBR扇区)中的64个字节中,每个分区项占用16个字节,这16个字节中…

如何将MBR转为GUID?这方法易于使用且安全!

为什么要将MBR转为GUID(GPT)? MBR代表主引导记录,它使用Legacy BIOS分区表。而GPT磁盘,也就是GUID分区表的缩写,是一种引入了统一可扩展固件接口 (UEFI) 的新布局。GPT磁盘有2个主要优势: GPT磁盘每个分区…

计算机硬盘分区信息,你知道电脑硬盘分区Guid格式和MBR格式有什么区别吗?来看看!...

现在的电脑随着技术的更新,传统的MBR格式虽然支持兼容,但是win10系统基本都使用了GUID分区格式,这样会让整体的系统运作得更有效率。如果还在使用MBR格式的用户想安装系统,没有设置好分区格式,容易导致安装出错&#x…

nvme分区选mbr还是guid_UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别

UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别?很多电脑小白都搞不懂UEFI、GPT、BIOS、MBR到底是什么意思,下面跟随小白系统一起深入了解下UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别吧。 一、了解专业名词 BIOS,全称"Basic Input Output System",中…

nvme分区选mbr还是guid_怎么分辨硬盘是GUID格式还是MBR格式以及怎样更改

首先我们要大概了解一下MBR和GUID是什么 mbr是指主引导记录,guid是指全局唯一标识符(其实我也不太懂这是啥),两者都是硬盘的一种启动模式(大概是这个意思,欢迎指教) 但是mbr只支持2x1024mb,也就是传统意义上的2tb的储存,并且只能分最多4个区,而guid理论上来讲可以有无…

nvme分区选mbr还是guid_系统重装,硬盘分区MBR和GPT选哪个好?看完才知原来有这讲究!...

在重装系统时,不少用户会问老毛桃电脑的硬盘选择MBR格式还是GPT格式好呢?其实,如何选择格式和你用的电脑是BIOS启动或是UEFI启动有很大的联系。我们都知道现在大家较为常用的要么是BIOS+MBR模式,要么是UEFI+GPT模式,选择任意一种模式的分区对系统运行不会造成太大的影响。…

nvme分区选mbr还是guid_重装系统时,磁盘分区MBR和GPT模式哪个好?原来还有这两种区别!...

相信大家在重装系统之前就会将电脑磁盘进行分区,毕竟只有一个分区是不可以进行重装系统的。而且磁盘分区方便管理磁盘,每个分区之间相互独立,数据不容易产生混淆。那么大家在创建磁盘分区的时候,肯定都会遇到MBR和GPT两种引导模式,这时候就会产生人生的思考:究竟应该怎么…

nvme分区选mbr还是guid_老毛桃winpe的DiskGenius分区工具使用说明

在对磁盘进行分区时,存在着一大堆的设置,到底需要如何设置?分区表是什么?如何进行4K对齐?以下操作建议PE下使用,前期需要准备:制作老毛桃U盘启动盘(U盘大小需要8G以上)。 操作指引: 起始分区操作请看:第1步 GUID分区表(GPT硬盘)操作请看:第2~7步; MBR分区表操作请看:…

服务器系统要用GUID还是MBR,win7mbr和guid应该选哪一个

win7mbr和guid是硬盘分区的两个格式,很多用户在做系统的时候不知道选哪个好,其实最好根据自己的电脑的配置,下面来看看详细的介绍吧。 win7mbr和guid选哪个 WIN7:建议MBR分区。因为Windows 7默认不支持UEFI系统安装,无…

服务器系统要用GUID还是MBR,分享win10分区格式MBR和GUID有什么区别 教你区分MBR和GUID格式...

今天IT天空小编要给大家分享下最新的教程 电脑装win10系统需要选择正确的分区格式,这样电脑才能保持正常运转,如果格式安装错误,电脑就没办法继续运行了。一般情况下,win10分区格式MBR和GUID两种选择,那么这两者有何区…