%hr = heartRateEstimation(imgDirectory, fps, windowDuration, windowShift) %%%%%%%%%%%%%%%%% % hr = heartRateEstimation(imgDirectory, fps, windowDuration, windowShift) % % Task: % % Inputs: % -imgDirectory % -fps % -windowDuration % -windowShift % % Output: % -hr: % % Author: Thomas Périn % Date: 17/02/2023 % % Note: images were extracted with ffmpeg -i "video.mkv" ../img/gg_%04d.png %%%%%%%%%%%%%%%%% clc clear all %temp var %imgDirectory = 'img'; fps = 15; windowDuration = 30; windowShift = 1; roi = [280 580 600 850]; % global redChannel = []; greenChannel = []; blueChannel = []; %list the images %listImg = dir([imgDirectory '/*.png']); listImg = dir(['*.png']); for l_img=1:windowDuration*fps % load the current image %image_original = imread([imgDirectory '/' listImg(l_img).name]); image_original = imread([listImg(l_img).name]); %image(image_original); %imshow([listImg(l_img).name]) % crop the current image around the face image_face = image_original(roi(1):roi(2), roi(3):roi(4), :); %image(image_face); % spatial average for r, g, b channels r_mean = mean(mean(image_face(:,:,1))); g_mean = mean(mean(image_face(:,:,2))); b_mean = mean(mean(image_face(:,:,3))); % store the current "average" pixel in global arrays redChannel = [redChannel r_mean]; greenChannel = [greenChannel g_mean]; blueChannel = [blueChannel b_mean]; end % estimate temporal average and standard deviation redChannel_avg = mean(redChannel); redChannel_std = std(redChannel); greenChannel_avg = mean(greenChannel); greenChannel_std = std(greenChannel); blueChannel_avg = mean(blueChannel); blueChannel_std = std(blueChannel); % normalize your data %first define length of our data L = columns(greenChannel); for i=1:L greenChannel_normalized(i) = (greenChannel(i) - greenChannel_avg)/greenChannel_std; end greenChannel_fft = fft(greenChannel_normalized); % power spectrum (https://www.mathworks.com/help/matlab/ref/fft.html) P2 = abs(greenChannel_fft/L); P1 = P2(1:L/2+1); P1(2:end-1) = 2*P1(2:end-1); f = 15*(0:(L/2))/L; plot(f,P1) % find the peak in the range ([0.75 4] Hz) % max -> value, index low_index = 0.75*L/15+0.5 high_index = 2*L/15 a = max(P1(low_index:high_index)) heart_rate = f(a) % convert the index from Hz to bpm % determine heart rate