在Python中以Hz为单位绘制FFT频率

在Python中以Hz为单位绘制FFT频率,python,numpy,scipy,signal-processing,Python,Numpy,Scipy,Signal Processing,我正在实施本文中的方法: 其主要思想是使用10秒视频中的一组帧(N=300)测量心脏脉搏,因此帧速率等于30 fps red = [item[:,:,0] for item in imgs] green = [item[:,:,1] for item in imgs] blue = [item[:,:,2] for item in imgs] red_avg = [item.mean() for item in red] green_avg = [item.mean() for item i

我正在实施本文中的方法:

其主要思想是使用10秒视频中的一组帧(N=300)测量心脏脉搏,因此帧速率等于30 fps

red = [item[:,:,0] for item in imgs]
green = [item[:,:,1] for item in imgs]
blue = [item[:,:,2] for item in imgs]

red_avg = [item.mean() for item in red]
green_avg = [item.mean() for item in green]
blue_avg = [item.mean() for item in blue]

red_mean, red_std = np.array(red_avg).mean(), np.array(red_avg).std()
green_mean, green_std = np.array(green_avg).mean(), np.array(green_avg).std()
blue_mean, blue_std = np.array(blue_avg).mean(), np.array(blue_avg).std()

red_avg = [(item - red_mean)/red_std for item in red_avg]
green_avg = [(item - green_mean)/green_std for item in green_avg]
blue_avg = [(item - blue_mean)/blue_std for item in blue_avg]

data = np.vstack([signal.detrend(red_avg), signal.detrend(green_avg), signal.detrend(blue_avg)]).reshape(300,3)
from sklearn.decomposition import FastICA
transformer = FastICA(n_components=3)
X_transformed = transformer.fit_transform(data)

from scipy.fftpack import fft

first = X_transformed.T[0]
second = X_transformed.T[1]
third = X_transformed.T[2]

ff = np.fft.fft(first)
fs = np.fft.fft(second)
ft = np.fft.fft(third)
imgs
-是具有300个图像像素值的阵列的初始列表。 如您所见,我将所有帧分割为RGB通道,因此具有跟踪
x_I(t)
,其中
I=1,2,3

在标准化之后,我们对所有的记录道进行去趋势化和叠加,以进一步应用ICA,然后对所有三个分量进行FFT

然后,该方法声称,我们需要绘制功率与频率(Hz)的关系图,并选择最有可能是心脏脉搏的成分

最后,我们对选定的源信号应用快速傅立叶变换(FFT)来 获得功率谱。脉冲频率被指定为 对应于工作频带内频谱的最高功率。对于 在我们的实验中,我们将工作范围设置为[0.75,4]Hz(对应于[45240] bpm)提供广泛的心率测量

以下是我如何尝试将频率可视化:

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

data = ft
print(fs.size)
ps = np.abs(np.fft.fft(data))**2

sampling_rate = 30

freqs = np.fft.fftfreq(data.size, 1/sampling_rate)
idx = np.argsort(freqs)
#print(idx)
plt.plot(freqs[idx], ps[idx])
我得到的是完全不同的,因为频率范围是从$15$到$15$,我不知道这是否是在赫兹

当我执行代码以可视化频率和信号功率时,上面的三幅图像就是我得到的


如果有任何帮助或建议,我将不胜感激

您应该真正了解如何使用图像/视频作为nD张量。这样,您就可以用更简洁的代码来代替所有的数据争论:

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft
from sklearn.decomposition import FastICA

images = [np.random.rand(640, 480, 3) for _ in range(30)]

# Create tensor with all images
images = np.array(images)
images.shape

# Take average of all pixels, for each image and each channel individually
avgs = np.mean(images, axis=(1, 2))
mean, std = np.mean(avgs), np.std(avgs)

# Normalize all average channels
avgs = (avgs - mean) / std

# Detrend across images
avgs = scipy.signal.detrend(avgs, axis=0)

transformer = FastICA(n_components=3)
X_transformed = transformer.fit_transform(avgs)

X_ff = np.fft.fft(X_transformed, axis=0)
plt.plot(np.abs(X_ff) ** 2)
稍微回答一下您的问题:我认为您错误地获取了第三个PCA分量的傅立叶谱的傅立叶谱

FFT(FFT(PCA[:, 2]))
虽然您打算只进行一次FFT:

FFT(PCA[:, 2]))
关于-15…15轴:您已将采样频率设置为30Hz(或视频中的30fps)。这意味着你可以在视频中检测到高达15Hz的任何东西

在傅里叶理论中,存在一种称为“负频率”的东西。现在,由于我们主要分析真实信号(与复杂信号相反),负频率总是与正频率相同。这意味着你的光谱总是对称的,你可以忽略左半部分

然而,因为你已经做了两次FFT,你看到的是复信号的FFT,它的频率是负的。这就是为什么你的光谱是不对称和混乱的

此外,我相信你混淆了重塑和转置。在PCA之前,您正在收集数据,如

np.vstack([red, green, blue])  # shape = (3, 300)

您要将其转置以获得
(300,3)
。如果改为重塑,则不是交换行和列,而是以不同的形状解释相同的数据。

您应该真正了解如何将图像/视频用作nD张量。这样,您就可以用更简洁的代码来代替所有的数据争论:

import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft
from sklearn.decomposition import FastICA

images = [np.random.rand(640, 480, 3) for _ in range(30)]

# Create tensor with all images
images = np.array(images)
images.shape

# Take average of all pixels, for each image and each channel individually
avgs = np.mean(images, axis=(1, 2))
mean, std = np.mean(avgs), np.std(avgs)

# Normalize all average channels
avgs = (avgs - mean) / std

# Detrend across images
avgs = scipy.signal.detrend(avgs, axis=0)

transformer = FastICA(n_components=3)
X_transformed = transformer.fit_transform(avgs)

X_ff = np.fft.fft(X_transformed, axis=0)
plt.plot(np.abs(X_ff) ** 2)
稍微回答一下您的问题:我认为您错误地获取了第三个PCA分量的傅立叶谱的傅立叶谱

FFT(FFT(PCA[:, 2]))
虽然您打算只进行一次FFT:

FFT(PCA[:, 2]))
关于-15…15轴:您已将采样频率设置为30Hz(或视频中的30fps)。这意味着你可以在视频中检测到高达15Hz的任何东西

在傅里叶理论中,存在一种称为“负频率”的东西。现在,由于我们主要分析真实信号(与复杂信号相反),负频率总是与正频率相同。这意味着你的光谱总是对称的,你可以忽略左半部分

然而,因为你已经做了两次FFT,你看到的是复信号的FFT,它的频率是负的。这就是为什么你的光谱是不对称和混乱的

此外,我相信你混淆了重塑和转置。在PCA之前,您正在收集数据,如

np.vstack([red, green, blue])  # shape = (3, 300)

您要将其转置以获得
(300,3)
。如果改为重塑,则不会交换行和列,而是以不同的形状解释相同的数据。

非常感谢您的详细评论。你能详细解释一下你所说的“进行两次FFT”是什么意思吗?该论文提出的模型建议在独立分量分析之后应用FFT对树迹分量进行分析。所以,据我所知,我只应用FFT一次。另一个问题是我应该如何解释频率。我不太理解文章中的这句话:
脉冲频率被指定为与工作频带内频谱的最高功率相对应的频率。在我们的实验中,我们将操作范围设置为[0.75,4]Hz
查看第一个代码段的底部和第二个代码段的顶部。你调用了两次
fft()
。我相信
np.vstack().restrape(300,3)
并没有像你想象的那样。你应该改为
np.vstack().T
。在你的例子中是Hz,是的。你正在以30Hz的频率对信号进行采样,并相应地生成一个轴。4Hz来自于对人体的了解:健康参与者的心率低于0.7或高于4Hz(42-210 bpm)是不可能的,因此可以忽略它。只需相应地裁剪你的频谱。不,只需丢弃超出该范围的频率和数据。非常感谢你的详细评论。你能详细解释一下你所说的“进行两次FFT”是什么意思吗?该论文提出的模型建议在独立分量分析之后应用FFT对树迹分量进行分析。所以,据我所知,我只应用FFT一次。另一个问题是我应该如何解释频率。我不太理解文章中的这句话:
脉冲频率被指定为与工作频带内频谱的最高功率相对应的频率。对于