real time smartphone camera processing v2
Show older comments
I have this code:
url = 'http://192.168.1.108:8080/shot.jpg'; % single frame source
cam = imread(url); % read source
% Parameters to play with
WINDOW_SECONDS = 4;
BPM_L = 40; BPM_H = 230; % [bpm] Valid heart rate range
FILTER_STABILIZATION_TIME = 1; % [s] Filter startup transient
CUT_START_SECONDS = 0; % [s] Initial signal period to cut off
FINE_TUNING_FREQ_INCREMENT = 1; % [bpm] Separation between test tones for smoothing
fps = 20; % frame per second
i = 1;
y = [];
%first loop, get 5 seconds of data
while(size(y,2) ~= 100)
cam = imread(url); % read source
pic(:,:,i) = cam(:, :, 1); % take RED domain only
y(i) = sum(sum(pic(:,:,i))) / (size(cam, 1) * size(cam, 2));
i = i + 1
disp('Collecting data...');
end
% butterworth filter
[b, a] = butter(2, [(((BPM_L)/60)/fps*2) (((BPM_H)/60)/fps*2)]);
% 5-points moving average for smoothing
yfilt = filter(b, a, y);
% cuts the first second and takes the remaing for seconds of data
% The first second is the filter transient
y = yfilt((fps * max(FILTER_STABILIZATION_TIME, CUT_START_SECONDS))+1:size(yfilt, 2));
% Some initializations and precalculations
fcl = BPM_L / 60;
fch = BPM_H / 60;
bpm = [];
bpm_smooth = [];
% second loop
% step 1) make calculations on the first 4 seconds of data
% step 2) take the last 3 seconds
% step 3) add 20 new frames, that makes the array 4 seconds long again
% step 4) goto step 1)
while(1)
if(i==101)
% *********************** STEP 1 ***********************
for j=1:size(y,2)
gain = abs(fft(y));
il = floor(fcl * (size(y, 2) / fps))+1;
ih = ceil(fch * (size(y, 2) / fps))+1;
index_range = il:ih;
[pks, locs] = findpeaks(gain(index_range));
[max_peak_v, max_peak_i] = max(pks);
max_f_index = index_range(locs(max_peak_i));
bpm(j) = (max_f_index-1) * (fps / size(y, 2)) * 60;
freq_resolution = 1 / WINDOW_SECONDS;
lowf = bpm(j) / 60 - 0.5 * freq_resolution;
freq_inc = FINE_TUNING_FREQ_INCREMENT / 60;
test_freqs = round(freq_resolution / freq_inc);
power = zeros(1, test_freqs);
freqs = (0:test_freqs-1) * freq_inc + lowf;
for h = 1:test_freqs,
re = 0; im = 0;
for k = 0:(size(y, 2) - 1),
phi = 2 * pi * freqs(h) * (j / fps);
re = re + y(k+1) * cos(phi);
im = im + y(k+1) * sin(phi);
end
power(h) = re * re + im * im;
end
[max_peak_v, max_peak_i] = max(power);
bpm_smooth(j) = 60*freqs(max_peak_i);
% ******************************************************
end
disp(['Mean HR: ' num2str(mean(bpm_smooth)) ' bpm']);
disp('.');
% *** STEP 2 ***
y = y(20:80);
i = 60;
% **************
end
% ************************ STEP 3 ***************************
i = i + 1;
cam = imread(url);
pic(:,:,i) = cam(:, :, 1); % take RED domain only
y(i) = sum(sum(pic(:,:,i))) / (size(cam, 1) * size(cam, 2));
% ***********************************************************
end
This code does the following:
- read frames from webcam source (20 / sec)
- calculate BPM
- do it again in a neverending loop always with the new data that comes meantime
It does not work like I wanted.. first sec 105bpm, next second 60. It fluctuates badly. How should I correct it?

Answers (0)
Categories
Find more on Digital Filter Analysis in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!