需要基于一些散点拟合椭圆估计并计算出椭圆的参数和周长,搜罗到直接上代码
(1)有用的椭圆拟合及参数计算函数
cpp
function W = fitellipse(x,y)
% 构造矩阵
D = [x.*x, x.*y, y.*y, x, y,ones(size(x))];
S = D'*D;
G = zeros(6);
G(1,3) = 2; G(3,1) = 2; G(2,2) = -1;
% 求解
[vec, val] = eig(S\G);
[~, idx] = find(val>0&~isinf(val));
W = vec(:,idx);
W = sqrt(1/(W'*S*W))*W;
end
cpp
function [Center,Axis,Theta] = calellipseparams(W)
a = W(1);
b = W(2);
c = W(3);
d = W(4);
e = W(5);
f = W(6);
% 中心
cx = (b*e-2*c*d)/(4*a*c-b^2);
cy = (b*d-2*a*e)/(4*a*c-b^2);
Center = [cx,cy];
% 长短轴
MA1 = sqrt(2*(a*cx^2+c*cy^2+b*cx*cy-f)/(a+c+sqrt((a-c)^2+b^2)));
MA2= sqrt(2*(a*cx^2+c*cy^2+b*cx*cy-f)/(a+c-sqrt((a-c)^2+b^2)));
Axis = [max(MA1,MA2),min(MA1,MA2)];
% 长轴倾角
if b==0
if f*a>f*c
Theta = 0;
else
Theta = pi/2;
end
else
if f*a>f*c
alpha = atan((a-c)/b);
if alpha<0
Theta = 0.5*(-pi/2-alpha);
else
Theta = 0.5*(pi/2-alpha);
end
else
alpha = atan((a-c)/b);
if alpha<0
Theta = pi/2+0.5*(-pi/2-alpha);
else
Theta = pi/2+0.5*(pi/2-alpha);
end
end
end
end
cpp
function C=drawellipse(W)
% 获取椭圆参数:中心、长、短半轴和长轴倾角
[Center,Axis,Theta] = calellipseparams(W);
% 绘制椭圆
funs = @(x,y) W(1)*x.^2 + W(2)*x.*y + W(3)*y.^2 + W(4)*x + W(5)*y + W(6);
fimplicit(funs,'LineWidth',2)
% 绘制长短轴
Majcoor = [-Axis(1),0; Axis(1),0];
Mincoor = [0,-Axis(2); 0,Axis(2)];
RM = [cos(Theta),-sin(Theta);sin(Theta),cos(Theta)];
Majcoor = Majcoor*RM'+Center;
Mincoor = Mincoor*RM'+Center;
Slen = sqrt((Mincoor(1,1)-Mincoor(2,1))^2 + (Mincoor(1,2)-Mincoor(2,2))^2);
Llen = sqrt((Majcoor(1,1)-Majcoor(2,1))^2 + (Majcoor(1,2)-Majcoor(2,2))^2);
C =(3.1415926*Slen+2*(Llen-Slen));
line(Majcoor(:,1),Majcoor(:,2),'Color','r','LineWidth',3)
line(Mincoor(:,1),Mincoor(:,2),'Color','g','LineWidth',3)
plot(Center(1),Center(2),'y.','MarkerSize',15)
end
(2)利用以上函数对已有散点进行椭圆拟合,并计算椭圆的周长如下:
cpp
XX=[....];%需拟合的散点
YY=[.....];
% 椭圆拟合
W = fitellipse(YY',ZZ');%输入参数为列向量且长度一致,不是列向量时需要转置
% 绘制结果
figure
plot(YY,ZZ,'.'),
axis equal
hold on
C=drawellipse(W);%返回椭圆周长
axis equal
下面是本次拟合的结果,看起来还不错,