Getting the right frequency (using FFT)

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

• Hi Don- Thanks for the post--- this is an lot for anyone to go through, and when I did I can't really make out what your question actually is. It would be helpful if you narrow down your focus (considerably) to a core question or problem you are having- and describing that in the simplest possible form. – Dan Boschen Dec 11 '19 at 23:37