[英]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.