123 lines
2.9 KiB
Matlab
123 lines
2.9 KiB
Matlab
clear;
|
|
|
|
addpath('../PDM_helpers/');
|
|
|
|
%% Create the PDM using PCA, from the recovered 3D data
|
|
clear
|
|
load('Torr_wild');
|
|
|
|
% need to still perform procrustes though
|
|
|
|
x = P3(1:end/3,:);
|
|
y = P3(end/3+1:2*end/3,:);
|
|
|
|
% To make sure that PDM faces the right way (positive Z towards the screen)
|
|
z = -P3(2*end/3+1:end,:);
|
|
|
|
brow_ids = 18:27;
|
|
|
|
%%
|
|
[ normX, normY, normZ, meanShape, Transform ] = ProcrustesAnalysis3D(x,y,z, true);
|
|
|
|
normX = normX(:, brow_ids);
|
|
normY = normY(:, brow_ids);
|
|
normZ = normZ(:, brow_ids);
|
|
meanShape = meanShape(brow_ids,:);
|
|
% make it zero centered now?
|
|
offsets = mean(meanShape);
|
|
|
|
normX = normX - offsets(1);
|
|
normY = normY - offsets(1);
|
|
normZ = normZ - offsets(1);
|
|
|
|
observations = [normX normY normZ];
|
|
|
|
[princComp, score, eigenVals] = princomp(observations,'econ');
|
|
% Keeping most variation
|
|
totalSum = sum(eigenVals);
|
|
count = numel(eigenVals);
|
|
for i=1:numel(eigenVals)
|
|
if ((sum(eigenVals(1:i)) / totalSum) >= 0.999)
|
|
count = i;
|
|
break;
|
|
end
|
|
end
|
|
|
|
load('pdm_68_multi_pie.mat', 'M');
|
|
M_full = M;
|
|
|
|
V = princComp(:,1:count);
|
|
E = eigenVals(1:count);
|
|
M = meanShape(:);
|
|
|
|
left_corner = [M(1); M(1+10)];
|
|
right_corner = [M(10); M(10+10)];
|
|
|
|
dist_norm = norm(left_corner - right_corner,2);
|
|
|
|
left_corner_full = [M_full(18); M_full(18+68)];
|
|
right_corner_full = [M_full(27); M_full(27+68)];
|
|
|
|
dist_norm_full = norm(left_corner_full - right_corner_full,2);
|
|
|
|
% average human interocular distance is 65mm
|
|
scaling = dist_norm_full / dist_norm;
|
|
|
|
% normalise the mean values as well
|
|
M(1:end/3) = M(1:end/3) - mean(M(1:end/3));
|
|
M(end/3+1:2*end/3) = M(end/3+1:2*end/3) - mean(M(end/3+1:2*end/3));
|
|
M(2*end/3+1:end) = M(2*end/3+1:end) - mean(M(2*end/3+1:end));
|
|
|
|
M = M * scaling;
|
|
E = E * scaling .^ 2;
|
|
|
|
% orthonormalise V
|
|
scalingV = sqrt(sum(V.^2));
|
|
V = V ./ repmat(scalingV, numel(M),1);
|
|
|
|
E = E .* (scalingV') .^ 2;
|
|
|
|
%% Also align the model to a Multi-PIE one for accurate head orientation
|
|
% also align the mean shape model (an aligned 68 point PDM from Multi-PIE dataset)
|
|
M_mouth = M;
|
|
|
|
load('pdm_68_multi_pie.mat', 'M');
|
|
M_align = M;
|
|
|
|
n_points = numel(M)/3;
|
|
M_mouth_full = reshape(M_align, n_points,3);
|
|
M_mouth_full = M_mouth_full(brow_ids, :);
|
|
|
|
n_points_mouth = numel(brow_ids);
|
|
|
|
M_mouth = reshape(M_mouth, n_points_mouth, 3);
|
|
|
|
% work out the translation and rotation needed
|
|
[ R, T ] = AlignShapesKabsch(M_mouth, M_mouth_full);
|
|
|
|
% Transform the wild one to be in the same reference as the Multi-PIE one
|
|
M_aligned = (R * M_mouth')';
|
|
|
|
M_aligned = M_aligned(:);
|
|
V_aligned = V;
|
|
|
|
% need to align the principal components as well
|
|
for i=1:size(V,2)
|
|
|
|
V_aligned_pie_curr = (R * reshape(V(:,i), n_points_mouth, 3)')';
|
|
V_aligned(:,i) = V_aligned_pie_curr(:);
|
|
|
|
end
|
|
|
|
V = V_aligned;
|
|
M = M_aligned;
|
|
|
|
save('pdm_10_brows.mat', 'E', 'M', 'V');
|
|
|
|
writePDM(V, E, M, 'pdm_10_brows.txt');
|
|
|
|
% also save this to model location
|
|
if(exist('../../models/pdm/', 'file'))
|
|
save('../../models/pdm/pdm_10_brows.mat', 'E', 'M', 'V');
|
|
end
|