Optimise scaling factor for 3D points
Show older comments
I have two matrices of point positions in 3D space, and I want to find the optimal scaling in x,y and z directions of one set of points to minimise the difference between the sets of points (so one scaling value for each direction for all points).
I currently have written a script to do this, and a separate script to optimise the rotation of the points. The scripts iterate through several different scaling factors/rotations then plot the difference and differentiate to find the minimum.
Now I want to try and use the optimisation toolbox to optimise both simultaneously but I am struggling... I have come across the Procrustes Analysis in Matlab, but really need separate scaling factors in x, y and z.
Any help would be fab, thanks.
2 Comments
Walter Roberson
on 19 Nov 2015
Are the matrices the same size? Is there to be a one-to-one correspondence between points, or just an overall shape?
awinka
on 19 Nov 2015
Answers (1)
Alan Weiss
on 19 Nov 2015
If I understand you correctly, the transformations you are willing to perform are rotation in 3-D space, and linear scaling in each coordinate direction. Are you also willing to recenter the points, meaning add an arbitrary translation? Are you willing to reflect the points, meaning use a rotation with negative determinant?
A rotation matrix has three parameters, the three rotational angles. Translation takes another three parameters, one for each coordinate direction, if you are willing to consider this. And scaling in each coordinate direction takes another three parameters. So you might have up to 9 parameters.
Your code would look something like this for the objective function:
function f = objfn(x,M1,M2) % The two matrices are M1 and M2
theta1 = x(1);
theta2 = x(2);
theta3 = x(3);
% Do the three rotations here, multiplying M1 by the
% three rotation matrices
% Then do the three translations:
M1(:,1) = M1(:,1) + x(4);
M1(:,2) = M1(:,2) + x(5);
M1(:,3) = M1(:,3) + x(6);
% Now the three dilations
M1(:,1) = M1(:,1)*x(7);
%etc
% Then compare the two point matrices
y = norm(M1 - M2)
Optimize the function as follows:
fun = @(x)objfn(x,M1,M2);
% Make an initial point x0. Then:
x = fminunc(fun,x0);
Good luck,
Alan Weiss
MATLAB mathematical toolbox documentation
8 Comments
awinka
on 19 Nov 2015
Torsten
on 20 Nov 2015
Did you put both parts of Alan's code in separate .m-files ?
Best wishes
Torsten.
awinka
on 20 Nov 2015
awinka
on 24 Nov 2015
Alan Weiss
on 24 Nov 2015
You seem to have misunderstood how you pass data. Either define M1 and M2 in your workspace before you begin, or change the function definition not to require them, but as it is you both pass them in and then overwrite them in your function, which is nonsensical.
You should probably have x0 as a column vector, not a row vector.
Why do you have all those definitions of thetai and scalei when you don't use those variables? If they are for your information, comment them out.
And now for the heart of the matter: your line
M2 = M1 * rot1 * rot2 * rot3;
is incorrect. You don't want to rotate and scale M1, and then compare it to M1. Obviously, the best thing to do in that case is not to rotate or scale at all. Instead, you should use
M2 = M2 * rot1 * rot2 * rot3;
And please double-check that you are multiplying the correct way; I am not sure if you should instead be writing
M2 = rot3 * rot2 * rot1 * M2;
Alan Weiss
MATLAB mathematical toolbox documentation
awinka
on 24 Nov 2015
Alan Weiss
on 24 Nov 2015
The first line should say
function y = objfn(x,M1,M2) % The two matrices are M1 and M2
Alan Weiss
MATLAB mathematical toolbox documentation
Categories
Find more on Solver Outputs and Iterative Display 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!