matlab练习程序(空间椭圆拟合)

之前实现过三维椭圆拟合,当时是利用已知点先进行椭球拟合,再进行平面拟合,通过解两个面的相交线得到空间椭圆函数。

如果只知道空间坐标可以用上述的方法,但是通常我们获得空间点时会附带时间信息,因此我们可以认为三个分量都是时间的函数,来进行拟合。

函数如下:

由于是非线性方程组,下面我们只需要用高斯牛顿法或者LM法计算非线性最小二乘就可以了。

代码如下:

clear all;
close all;
clc;

warning off;
A = rand(1,3);
B = rand(1,3);
C = rand(1,3);

t = 0:0.01:2*pi;
p=[];
for i=1:length(t)
    x =  C(1) + A(1)*cos(t(i)) + B(1)*sin(t(i));
    y =  C(2) + A(2)*cos(t(i)) + B(2)*sin(t(i));
    z =  C(3) + A(3)*cos(t(i)) + B(3)*sin(t(i));
    p=[p;x y z];
end

selectnum = 50;
ind = randperm(length(p),selectnum);   
t = t(ind)';
data = p(ind,:) + (rand(selectnum,3)-0.5)/10;

plot3(p(:,1),p(:,2),p(:,3),'.');
grid on;
hold on;
plot3(data(:,1),data(:,2),data(:,3),'r*');

X = data(:,1);
Y = data(:,2);
Z = data(:,3);

prex = rand(3,1);
prey = rand(3,1);
prez = rand(3,1);
for i=1:500
    
    Fx = prex(1) + prex(2)*cos(t) + prex(3)*sin(t);
    Fy = prey(1) + prey(2)*cos(t) + prey(3)*sin(t);
    Fz = prez(1) + prez(2)*cos(t) + prez(3)*sin(t);
    
    Gx = X - Fx;
    Gy = Y - Fy;
    Gz = Z - Fz;
    
    Dc = ones(length(t),1);
    Da = cos(t);
    Db = sin(t);
    J = [Dc Da Db];
    
    deltax = inv(J'*J)*J'* Gx;
    deltay = inv(J'*J)*J'* Gy;
    deltaz = inv(J'*J)*J'* Gz;
    
    pcurx = prex+deltax;
    pcury = prey+deltay;
    pcurz = prez+deltaz;
    
    prex = pcurx;
    prey = pcury;
    prez = pcurz;
end

t = 0:0.01:2*pi;
p=[];
for i=1:length(t)
    x =  prex(1) + prex(2)*cos(t(i)) + prex(3)*sin(t(i));
    y =  prey(1) + prey(2)*cos(t(i)) + prey(3)*sin(t(i));
    z =  prez(1) + prez(2)*cos(t(i)) + prez(3)*sin(t(i));
    p=[p;x y z];
end

plot3(p(:,1),p(:,2),p(:,3),'go');

拟合结果:

蓝色点为原始椭圆。

红色星为蓝色点中选50个点并且加入噪声后的点。

绿色圈为拟合结果。

posted @ 2021-01-26 21:15  Dsp Tian  阅读(2054)  评论(0编辑  收藏  举报