I am implementing the method from this paper: https://dspace.mit.edu/bitstream/handle/1721.1/66243/Picard_Noncontact%20Automated.pdf?sequence=1&isAllowed=y
The main idea is cardiac pulse measurement using a set of frames ($N=300$) from a 10s video so the frame rate equals $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 second = X_transformed.T third = X_transformed.T ff = np.fft.fft(first) fs = np.fft.fft(second) ft = np.fft.fft(third)
imgs - is the initial list of arrays with 300 image pixel values.
As you can see, I split all frames into RGB channels and thus have traces $x_i(t)%$, where $i = 1,2,3$
After standardization, we detrend all the traces and stack them to further apply ICA and then FFT all the three components.
The method then claims that we need to plot power vs frequency (Hz) and select the component that is most likely to be heart pulse.
Finally, we applied the fast Fourier transform (FFT) on the selected source signal to obtain the power spectrum. The pulse frequency was designated as the frequency that corresponded to the highest power of the spectrum within an operational frequency band. For our experiments, we set the operational range to [0.75, 4] Hz (corresponding to [45, 240] bpm) to provide a wide range of heart rate measurements.
Here's how I try to visualize the frequencies:
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])
What I get is totally different since the range of frequencies is from $-15$ to $15$ and I have no idea whether this is in Hz or not.
The three images above are what I get when I execute the code to visualize frequencies and signal power.
I would appreciate any help or suggestions.