141 lines
3.4 KiB
Matlab
141 lines
3.4 KiB
Matlab
|
|
%%%%%%%%%%%%%%%%%
|
|
%
|
|
%
|
|
% Task: Detect heart rate through video
|
|
%
|
|
%
|
|
%
|
|
% Authord: Estevan Biau-Loyer & Darren Gallois
|
|
% Date: 19/02/2023
|
|
%
|
|
%%%%%%%%%%%%%%%%%
|
|
|
|
|
|
% Loop through the images selected
|
|
|
|
% Initialize a matrix to store RGB values
|
|
all_rgb = zeros(900, 3, 61, 101);
|
|
|
|
% Initialize iteration
|
|
a=0;
|
|
for i = 100:1000
|
|
% Set the image path
|
|
image_path = imread(sprintf('frame2_%d.jpg', i));
|
|
[rows, columns, channels] = size(image_path);
|
|
%Create the ROI
|
|
roi = image_path(90:150, 300:400, :);
|
|
% Save the images adjusted to the ROI
|
|
imwrite(roi, (sprintf('frames/my_imagev2%d.jpg',i)));
|
|
end
|
|
|
|
% Loop through 900 images
|
|
for i = 100:1000
|
|
% Read image
|
|
img = imread(sprintf('frames/my_imagev2%d.jpg', i));
|
|
|
|
% Convert to double precision
|
|
img = im2double(img);
|
|
|
|
% Separate RGB channels
|
|
red = img(:,:,1);
|
|
green = img(:,:,2);
|
|
blue = img(:,:,3);
|
|
|
|
% Store RGB channels in the matrix
|
|
all_rgb(i, 1, :, :) = red;
|
|
all_rgb(i, 2, :, :) = green;
|
|
all_rgb(i, 3, :, :) = blue;
|
|
a=a+1;
|
|
|
|
% Display iteration
|
|
disp(a);
|
|
end
|
|
|
|
% Compute mean RGB values for each image
|
|
mean_rgb = squeeze(mean(mean(all_rgb, 4), 3));
|
|
save('mean_rgb.m', 'mean_rgb');
|
|
|
|
% Load the mean RGB values from the .m file
|
|
load('mean_rgb.m');
|
|
|
|
% Get the number of images
|
|
num_images = size(mean_rgb, 1);
|
|
|
|
% Create a vector of indices for each image
|
|
indices = 1:num_images;
|
|
|
|
% Plot the green channel
|
|
figure;
|
|
plot(indices, mean_rgb(:, 1), 'r');
|
|
hold on;
|
|
|
|
% Plot the red channel
|
|
plot(indices, mean_rgb(:, 2), 'g');
|
|
|
|
% Plot the blue channel
|
|
plot(indices, mean_rgb(:, 3), 'b');
|
|
|
|
% Add legend and labels
|
|
legend({'Red', 'Green', 'Blue'});
|
|
xlabel('Image index');
|
|
ylabel('Mean RGB value');
|
|
|
|
% Get the standard deviation of each color
|
|
red_std = std(mean_rgb(:, 1));
|
|
green_std = std(mean_rgb(:, 2));
|
|
blue_std = std(mean_rgb(:, 3));
|
|
|
|
% Get the average value of each color
|
|
red_avg = mean(mean_rgb(:, 1));
|
|
green_avg = mean(mean_rgb(:, 2));
|
|
blue_avg = mean(mean_rgb(:, 3));
|
|
|
|
% Normalize the values
|
|
red_normalized = (mean_rgb(:, 1) - red_avg)/red_std
|
|
green_normalized = (mean_rgb(:, 2) - green_avg)/green_std
|
|
blue_normalized = (mean_rgb(:, 3) - blue_avg)/blue_std
|
|
|
|
% Create the 3 channels fft
|
|
red_fft = fft(red_normalized)
|
|
green_fft = fft(green_normalized)
|
|
blue_fft = fft(blue_normalized)
|
|
|
|
N = length(red_normalized); % length of the signal
|
|
freq = fftshift(fftfreq(N)); % frequency vector in Hz
|
|
|
|
% plot the FFT result for the three channels
|
|
figure;
|
|
hold on;
|
|
plot(freq, abs(red_fft));
|
|
|
|
plot(freq, abs(green_fft));
|
|
|
|
plot(freq, abs(blue_fft));
|
|
hold off;
|
|
|
|
xlabel('Frequency (Hz)');
|
|
ylabel('Magnitude');
|
|
legend({'Red', 'Green', 'Blue'});
|
|
|
|
% Find indices in f that correspond to the frequency range of interest
|
|
idx_range = find(f >= 0.75 & f <= 4);
|
|
|
|
% Extract the amplitude values in the range of interest for each channel
|
|
red_amp_range = abs(red_fft(idx_range));
|
|
green_amp_range = abs(green_fft(idx_range));
|
|
blue_amp_range = abs(blue_fft(idx_range));
|
|
|
|
% Find the index of the maximum amplitude value in the range of interest for each channel
|
|
[red_max_amp, red_max_idx] = max(red_amp_range);
|
|
[green_max_amp, green_max_idx] = max(green_amp_range);
|
|
[blue_max_amp, blue_max_idx] = max(blue_amp_range);
|
|
|
|
% Convert index of maximum amplitude value to frequency, and then to bpm
|
|
red_bpm = f(idx_range(red_max_idx)) * 60;
|
|
green_bpm = f(idx_range(green_max_idx)) * 60;
|
|
blue_bpm = f(idx_range(blue_max_idx)) * 60;
|
|
|
|
% Determine heart rate by taking the average of the bpm values for the three channels
|
|
heart_rate = mean([red_bpm, green_bpm, blue_bpm]);
|
|
disp(heart_rate); |