簡體   English   中英

在 Python 中以 Hz 為單位繪制 FFT 頻率

[英]Plotting FFT frequencies in Hz in Python

我正在實施本文中的方法: https : //dspace.mit.edu/bitstream/handle/1721.1/66243/Picard_Noncontact%20Automated.pdf?sequence=1&isAllowed=y

主要思想是使用來自 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(對應於 [45, 240] 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$,我不知道這是否以 Hz 為單位。

方法理念

文章中的圖表

第一個組件

第二個組件

第三部分

上面三張圖片是我執行代碼以可視化頻率和信號功率時得到的結果。

我將不勝感激任何幫助或建議。

您應該真正學習如何將圖像/視頻作為 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) 如果您改用整形,則不會交換行和列,而是以不同的形狀解釋相同的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM