diff --git a/FFT_heart_rate.m b/FFT_heart_rate.m new file mode 100644 index 0000000..1989734 --- /dev/null +++ b/FFT_heart_rate.m @@ -0,0 +1,66 @@ +%%%%%%%%%%%%%%%%%%%%% +% Script task: Normalize RGB data and plot FFT using the power spectra +% +% Input : RGB_data.csv -> average RGB values of each image +% +% Output : Fast Fourier Transform of X(t): a graph representing the Single-Sided Amplitude Spectrum of X(t) +% +% Author: Loic Delattre and Maryne DEY (maryne.dey@ecam.fr, loic.delattre@ecam.fr) +% Date: 07/02/2023 +%%%%%%%%%%%%%%%%%%%%% + +clear all +close all +clc + +%To be able to extract from external format (excel) +pkg load io + +%Normalization of the data +data = frames_RGBs ()'; +standard_deviation = std(data); +mean_value = mean(data); + +for i = 1:size(data,1) + normalized_data_G(i,1) = (data(i,2)-mean_value(2))/standard_deviation(2); %%2 and not 1 because green is the 2nd color +endfor + +%Input characteristics +img_num = length(data); +Fs = img_num/32; % Sampling frequency = X images in 32 seconds +T = 1/Fs; % Sampling period +L = img_num; % Length of signal = 32 seconds +t = (0:L-1)*T; % Time vector + +X = normalized_data_G; + +%Plot of the RGB data in the time domain +plot(t(1:L),X(1:L)) +title("Signal") +xlabel("t (milliseconds)") +ylabel("X(t)") + +%Finding power spectra P2 and P1 +Y = fft(X); +P2 = abs(Y/L); +P1 = P2(1:L/2+1); +P1(2:end-1) = 2*P1(2:end-1); +f = Fs*(0:(L/2))/L; + +% Finding boudaries +start = find(f==0.75); +stop = find(f==4); +P1_graph = P1(start:stop); +f_graph = f(start:stop); + +%Graph of FFT in function of the frequency +plot(f_graph,P1_graph) +title("Single-Sided Amplitude Spectrum of X(t)") +xlabel("f (Hz)") +ylabel("|P1(f)|") + +%Extracting the heart rate +[heart_rate_Hz, index] = max(P1_graph); +corresponding_frequency = f_graph(index); +heart_rate_bpm = corresponding_frequency*60; +fprintf("Your heart rate is about %d bpm.\n", heart_rate_bpm) \ No newline at end of file diff --git a/RGB_traces.m b/RGB_traces.m index 6f7ff06..e39dd23 100644 --- a/RGB_traces.m +++ b/RGB_traces.m @@ -10,7 +10,7 @@ % Output: % -RGB_avg: a 1x3 matrix with the RGB average values, format -> [R, G, B] % -% author: Loic Delattre (loic.delattre@ecam.fr) +% author: Maryne Dey and Loic Delattre (maryne.dey@ecam.fr, loic.delattre@ecam.fr) % date: 06/02/2023 %%%%%%%%%%%%%%%%%%%%% diff --git a/frames_RGBs.m b/frames_RGBs.m index decc610..b17235d 100644 --- a/frames_RGBs.m +++ b/frames_RGBs.m @@ -29,7 +29,7 @@ function RGB_data = frames_RGBs () endwhile catch disp('scanned all frames') - j = 10001 + j = 10001; end_try_catch endwhile diff --git a/get_frames.py b/get_frames.py index 252c5d9..0000598 100644 --- a/get_frames.py +++ b/get_frames.py @@ -3,14 +3,34 @@ import os.path import os from PIL import Image -# Opens the Video file +############### +# def get_frames(input1) +# ex. get_frames(video.mov) +# +# Task: Extracting frames from a video +# +# Inputs: +# - input1: a video +# +# Output: +# -RGB_avg: a directory with all the frames of the video +# +# author: Loic Delattre and Maryne Dey (loic.delattre@ecam.fr, maryne.dey@ecam.fr) +# date: 06/02/2023 +############### + + video = 'my_face.mov' -path_to_script = os.path.dirname(os.path.abspath(__file__)) -if os.path.exists(path_to_script + r"\frames") == False: - os.mkdir(path_to_script + r"\frames") + def get_frames(vid): + path_to_script = os.path.dirname(os.path.abspath(__file__)) + if os.path.exists(path_to_script + r"\frames") == False: + os.mkdir(path_to_script + r"\frames") + + # Opens the Video file cap= cv2.VideoCapture(vid) + i=0 while cap.isOpened(): ret, img = cap.read() @@ -21,15 +41,15 @@ def get_frames(vid): eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - faces = face_cascade.detectMultiScale(gray, 1.3, 5) + faces = face_cascade.detectMultiScale(gray, 1.3, 5) #detect the face in the frame for (x,y,w,h) in faces: - # To draw a rectangle in a face + # To draw a rectangle in a face for testing purposes cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] - eyes = eye_cascade.detectMultiScale(roi_gray) + eyes = eye_cascade.detectMultiScale(roi_gray) #detect the eyes in the frames taking the face as reference list_ex = [] list_ey = [] list_ew = [] @@ -37,7 +57,7 @@ def get_frames(vid): #To draw a rectangle in eyes for (ex,ey,ew,eh) in eyes: - if ew >= 80 and eh >= 80: + if ew >= 82 and eh >= 82: #cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,127,255),2) list_ex.append(ex) list_ey.append(ey) @@ -46,10 +66,10 @@ def get_frames(vid): #rectangle on forhead try: - fx = min(list_ex) + list_ew[list_ex.index(min(list_ex))] + fx = min(list_ex) + list_ew[list_ex.index(min(list_ex))] #deducing ROI from the eyes rectangle coordinates fy = max(list_ey) x1 = x + fx - x2 = x + fx + 100 + x2 = x + fx + 100 #extra values in x and y in the parameters are adjustements made after manual testing y1 = y + fy - 150 y2 = y + fy - 20 @@ -59,8 +79,9 @@ def get_frames(vid): i+=1 except: print('error on min value of ex') - #extra values in x and y in the parameters are adjustements made after manual testing - #cv2.rectangle(roi_color, (fx,fy-150),(fx+100,fy-20),(0,127,255),2) + #cv2.rectangle(roi_color, (fx,fy-150),(fx+100,fy-20),(0,127,255),2) #for testing purposes + #cv2.imshow('img',roi_color) + #cv2.waitKey(0) cap.release() cv2.destroyAllWindows() diff --git a/matrix_avg.m b/matrix_avg.m index a4f8b32..900ed86 100644 --- a/matrix_avg.m +++ b/matrix_avg.m @@ -10,7 +10,7 @@ % Output: % -RGB_avg: a 1x3 matrix with the RGB average values % -% author: Loic Delattre (loic.delattre@ecam.fr) +% author: Maryne Dey and Loic Delattre (maryne.dey@ecam.fr, loic.delattre@ecam.fr) % date: 06/02/2023 %%%%%%%%%%%%%%%%%%%%% diff --git a/normalization.m b/normalization.m deleted file mode 100644 index 88a9594..0000000 --- a/normalization.m +++ /dev/null @@ -1,38 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%% -% Task: Creating FFT of average R,G,B over a period of 30 seconds -% -% Input: -% - CSV file containing the RGB data for each pixels of the region of interest -% -% Output: -% - Fast Fourier Transform of the colors over time -% -% author: Delattre Loïc, Dey Maryne (loic.delattre@ecam.fr, maryne.dey@ecam.fr) -% date: 06/02/2023 -%%%%%%%%%%%%%%%%%%%%% - -pkg load io %% to be able to extract from external format (excel) - -data = csvread('RGB_database/RGB_data.csv') -standard_deviation = std(data) -mean_value = mean(data) - -for i = 1:size(data,1) - normalized_data_G(i,1) = (data(i,2)-mean_value(2))/standard_deviation(2); %%2 and not 1 because green is the 2nd color -endfor - -fft_green = fft(normalized_data_G) - -plot([1:size(fft_green,1)],fft_green) - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%For all the colors -%%for j = 1:3 -%% for i = 1:size(data,1) -%% normalized_data(i,j) = (data(i,j)-mean_value(j))/standard_deviation(j); -%% endfor -%%endfor -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ No newline at end of file diff --git a/test_file.m b/test_file.m index b120e6d..b6a9368 100644 --- a/test_file.m +++ b/test_file.m @@ -4,7 +4,8 @@ clc threshold = 1e-6; -RGB_data = frames_RGBs (); +RGB_data = frames_RGBs ()'; +length(RGB_data) %TEST 1 %Average of all the items inside of a matrix