open source pkg v1
This commit is contained in:
103
pkg/OpenFace/matlab_version/PDM_helpers/ProcrustesAnalysis.m
Normal file
103
pkg/OpenFace/matlab_version/PDM_helpers/ProcrustesAnalysis.m
Normal file
@@ -0,0 +1,103 @@
|
||||
function [normX, normY, meanShape, Transform] = ProcrustesAnalysis(x, y, options)
|
||||
|
||||
% Translate all elements to origin and scale to 1
|
||||
normX = zeros(size(x));
|
||||
normY = zeros(size(y));
|
||||
|
||||
for i = 1:size(x,1)
|
||||
|
||||
offsetX = mean(x(i,:));
|
||||
offsetY = mean(y(i,:));
|
||||
|
||||
Transform.offsetX(i) = offsetX;
|
||||
Transform.offsetY(i) = offsetY;
|
||||
|
||||
normX(i,:) = x(i,:) - offsetX;
|
||||
normY(i,:) = y(i,:) - offsetY;
|
||||
|
||||
% Get the Frobenius norm, to scale the shapes to unit size
|
||||
scale = norm([normX(i,:) normY(i,:)], 'fro');
|
||||
|
||||
Transform.scale(i) = scale;
|
||||
|
||||
normX(i,:) = normX(i,:)/scale;
|
||||
normY(i,:) = normY(i,:)/scale;
|
||||
|
||||
end
|
||||
|
||||
% Rotate elements untill all of them have the same orientation
|
||||
|
||||
% the initial estimate of rotation would be the first element
|
||||
% if change is less than 1% stop (shouldn't take more than 2 steps)
|
||||
change = 0.1;
|
||||
|
||||
meanShape = [ normX(1,:); normY(1,:) ]';
|
||||
|
||||
Transform.Rotation = zeros(size(x,1),1);
|
||||
|
||||
for i = 1:30
|
||||
|
||||
% align all of the shapes to the mean shape
|
||||
|
||||
% remember all orientations to get the mean one
|
||||
orientations = zeros(size(normX,1),1);
|
||||
|
||||
for j = 1:size(x,1)
|
||||
|
||||
% do SVD of mean * X'
|
||||
currentShape = [ normX(j,:); normY(j,:) ]';
|
||||
[U, ~, V] = svd( meanShape' * currentShape);
|
||||
rot = V*U';
|
||||
|
||||
if(asin(rot(2,1)) > 0)
|
||||
orientations(j) = real(acos(rot(1,1)));
|
||||
else
|
||||
orientations(j) = real(-acos(rot(1,1)));
|
||||
end
|
||||
|
||||
Transform.Rotation(j) = Transform.Rotation(j) + orientations(j);
|
||||
|
||||
currentShape = currentShape * rot;
|
||||
|
||||
normX(j,:) = currentShape(:,1)';
|
||||
normY(j,:) = currentShape(:,2)';
|
||||
|
||||
end
|
||||
|
||||
% recalculate the mean shape;
|
||||
oldMean = meanShape;
|
||||
meanShape = [mean(normX); mean(normY)]';
|
||||
|
||||
% rotate the mean shape to mean rotation
|
||||
meanOrientation = mean(orientations);
|
||||
|
||||
% Do this only the first time
|
||||
if(i==1)
|
||||
|
||||
rotM = [ cos(-meanOrientation) -sin(-meanOrientation); sin(-meanOrientation) cos(-meanOrientation) ];
|
||||
meanShape = meanShape * rotM;
|
||||
end
|
||||
% scale mean shape to unit
|
||||
meanScale = norm(meanShape, 'fro');
|
||||
meanShape = meanShape*(1/meanScale);
|
||||
|
||||
% find frobenious norm
|
||||
diff = norm(oldMean - meanShape, 'fro');
|
||||
|
||||
if(diff/norm(oldMean,'fro') < change)
|
||||
break;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% transform to tangent space to preserve linearities
|
||||
|
||||
% get the scaling factors for each shape
|
||||
if(options.TangentSpaceTransform)
|
||||
scaling = [ normX normY ] * [ meanShape(:,1)' meanShape(:,2)']';
|
||||
for i=1:size(x,1)
|
||||
normX(i,:) = normX(i,:) * (1 / scaling(i));
|
||||
normY(i,:) = normY(i,:) * (1 / scaling(i));
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user