data fitting an ellipse in 3D space

后端 未结 1 1244
难免孤独
难免孤独 2021-01-16 05:23

Forum

I\'ve got a set of data that apparently forms an ellipse in 3D space (not an ellipsoid, but a curve in 3D). Being inspired by following thread http://au.math

1条回答
  •  遥遥无期
    2021-01-16 05:31

    This answer is not a direct fit in 3D, it instead involves first a rotation of the data so that the plane of the points coincides with the xy plane, then a fit to the data in 2D.

    % input: data, a N x 3 array with one set of Cartesian coords per row
    
    % remove the center of mass
    CM = mean(data);
    datap = data - ones(size(data,1),1)*CM;
    
    
    % now rotate all points into the xy plane ...
    % start by finding the plane:
    
    [u s v]=svd(datap);
    
    % rotate the data into the principal axes frame:
    
    datap = datap*v;
    
    
    % fit the equation for an ellipse to the rotated points
    
    x= [0.25 0.07 0.037 0 0]'; % initial parameters    
    options=1;
    xopt = fmins(@fellipse,x,options,[],datap) % set the distance minimum as the target function
    

    This is the function fellipse, based on the function provided:

    function [merit]= fellipse(x,data) % x is the initial parameters, data stores the datapoints
    
    a = x(1);
    b = x(2);
    alpha = x(3);    
    z = x(4:5);
    
    R = [cos(alpha), sin(alpha), 0; -sin(alpha), cos(alpha), 0; 0, 0, 1];
    data = data*R; 
    
    merit = 0;
    
    [dim1, dim2]=size(data);
    for i=1:dim1
        dist=@(phi)sum( ( [a*cos(phi);b*sin(phi)] + z - data(i,1:2)').^2 ); 
        phi=fminbnd(dist,0,2*pi);
        merit = merit+dist(phi);
    end
    
    end
    

    Also, note again that this can be turned into a fit directly in 3D, but this answer is just as good if you can assume the data points lie approx. in a 2D plane. The current solution is likely much more efficient then a solution in 3D with additional parameters.

    Hopefully the code is self-explanatory. I recommend looking at the link included in the OP, it explains the purpose of the loop over phi.

    And this is how you can inspect the result of the fit:

    a = xopt(1);
    b = xopt(2);
    alpha = xopt(3);
    z = [xopt(4:5) ; 0]';
    
    phi = linspace(0,2*pi,100)';
    simdat = [a*cos(phi) b*sin(phi) zeros(size(phi))];
    R = [cos(alpha), -sin(alpha), 0; sin(alpha), cos(alpha), 0; 0, 0, 1];
    simdat = simdat*R  + ones(size(simdat,1), 1)*z ; 
    
    
    figure, hold on
    plot3(datap(:,1),datap(:,2),datap(:,3),'o')
    plot3(simdat(:,1),simdat(:,2),zeros(size(simdat,1),1),'r-')
    

    Edit

    The following is a 3D approach. It does not appear to be very robust as it is quite sensitive to the choice of starting parameters. Some improvements may be necessary.

    CM = mean(data);
    datap = data - ones(size(data,1),1)*CM;
    xopt = [  0.07 0.25 1 -0.408976 0.610120 0 0  0]';
    options=1;
    xopt = fmins(@fellipse3d,xopt,options,[],datap) % set the distance minimum as the target function
    

    The function fellipse3d is

    function [merit]= fellipse3d(x,data) % x is the initial parameters, data stores the datapoints
    
    a = abs(x(1));
    b = abs(x(2));
    alpha = x(3);
    beta = x(4);
    gamma = x(5);
    z = x(6:8)';
    
    [dim1, dim2]=size(data);
    
    R1 = [cos(alpha), sin(alpha), 0; -sin(alpha), cos(alpha), 0; 0, 0, 1];
    R2 = [1, 0, 0; 0, cos(beta), sin(beta); 0, -sin(beta), cos(beta)];
    R3 = [cos(gamma), sin(gamma), 0; -sin(gamma), cos(gamma), 0; 0, 0, 1];
    R = R3*R2*R1;
    
    data = (data - z(ones(dim1,1),:))*R; 
    
    merit = 0;
    for i=1:dim1
        dist=@(phi)sum( ([a*cos(phi);b*sin(phi);0]  - data(i,:)').^2 ); 
        phi=fminbnd(dist,0,2*pi);
        merit = merit+dist(phi);
    end
    end
    

    You can visualize the results with

    a = xopt(1);
    b = xopt(2);
    alpha = -xopt(3);
    beta = -xopt(4);
    gamma = -xopt(5);
    z = xopt(6:8)' + CM;
    
    dim1 = 100;
    phi = linspace(0,2*pi,dim1)';
    
    simdat = [a*cos(phi) b*sin(phi) zeros(size(phi))];
    
    R1 = [cos(alpha), sin(alpha), 0; ...
         -sin(alpha), cos(alpha), 0; ... 
            0, 0, 1];
    
    R2 = [1, 0, 0;  ...
          0, cos(beta), sin(beta);  ...
          0, -sin(beta), cos(beta)];
    
    R3 = [cos(gamma), sin(gamma), 0;  ...
          -sin(gamma), cos(gamma), 0;  ...
               0, 0, 1];
    
    R = R1*R2*R3;
    
    simdat = simdat*R + z(ones(dim1,1),:); 
    
    figure, hold on
    plot3(data(:,1),data(:,2),data(:,3),'o')
    plot3(simdat(:,1),simdat(:,2),simdat(:,3),'r-')
    

    0 讨论(0)
提交回复
热议问题