-
Notifications
You must be signed in to change notification settings - Fork 34
/
FVP.m
70 lines (54 loc) · 2.53 KB
/
FVP.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
% Thanks to Terbe Dániel for this script (a new version formated in the standard format will follow shortly.)
function H = FVP(frames, Fs)
%FVP Full Video Pulse extraction
% frames: sequence of RGB images (N, h, w, c)
% Fs: Frame rate
N = size(frames, 1);
K = 6;
L1 = Fs;
u0 = 1;
L2 = 128;
B = [6, 24]; % pulse band (calculated for L2!)
Jt = zeros(4*K, N, 3);
Pt = zeros(4 * K, N);
Zt = zeros(4*K, N);
H = zeros(1, N);
for i=1:N
% Generate weighting masks
Id = imresize(squeeze(frames(i,:,:,:)), [20, 20], 'box'); % downsize
D = reshape(bsxfun(@rdivide, Id, sum(Id, 3)), [size(Id, 1)*size(Id, 2), 3]);
A = pdist2(D, D, 'euclidean');
[u, ~, ~] = svds(A, K);
% correct the eigenvector signs
u = bsxfun(@times, u, sign(sum(u0.*u, 1)));
u0 = u;
w = [u(:,1:K), -u(:, 1 : K)]';
w = bsxfun(@minus, w, min(w, [], 2));
w = bsxfun(@rdivide, w, sum(w, 2));
% Weight and combine spatial pixel values
J = bsxfun(@times, reshape(Id, [1, size(Id, 1) * size(Id, 2), 3]), w);
Jt(:, i, :) = [mean(J, 2); var(J, [], 2)];
% Extract rPPg-signals (with POS)
if(i >= L1)
C = Jt(:, i - L1 + 1 : i, :);
Cn = bsxfun(@rdivide, C, mean(C, 2)) - 1;
X = Cn(:, :, 2) - Cn(:, :, 3); Y = Cn(:, :, 2) + Cn(:, :, 3) - 2 * Cn(:, :, 1);
P = X + bsxfun(@times, std(X, [], 2)./std(Y, [], 2), Y);
Z = Cn(:, :, 1) + Cn(:, :, 2) + Cn(:, :, 3);
Pt(:, i - L1 + 1 : i) = Pt(:, i - L1 + 1 : i) + bsxfun(@rdivide, bsxfun(@minus, P, mean(P, 2)), std(P, [], 2));
Zt(:, i - L1 + 1 : i) = Zt(:, i - L1 + 1 : i) + bsxfun(@rdivide, bsxfun(@minus, Z, mean(Z, 2)), std(Z, [], 2));
end
% Combine rPPG signals into pulse
if(i >= L2)
P = Pt(:, i - L2 + 1 : i);
Z = Zt(:, i - L2 + 1 : i);
Fp = fft(bsxfun(@rdivide, bsxfun(@minus, P, mean(P, 2)), std(P, [], 2)), [], 2)/L2;
Fz = fft(bsxfun(@rdivide, bsxfun(@minus, Z, mean(Z, 2)), std(Z, [], 2)), [], 2)/L2;
W = abs(Fp.* conj(Fp))./(1 + abs(Fz.* conj(Fz)));
W(:, 1 : B(1) - 1) = 0;
W(:, B(2) + 1 : end) = 0;
h = real(ifft(sum(W.* Fp, 1), [], 2));
H(:, i - L2 + 1 : i) = H(:, i - L2 + 1 : i) + (h - mean(h))/std(h);
end
end
end