Fit an ellipse to data.

18 Ansichten (letzte 30 Tage)
Carmine Buonagura
Carmine Buonagura am 17 Okt. 2020
Bearbeitet: Matt J am 18 Feb. 2022
I have some data with a shape that can be approximated to that of an ellipse. The data I have are as the ones in the following image:
I tried to fit noisy ellipse data with an fmincon algorithm: constraining the points of the ellipse to be as closer as possible to that of the boundary but at the same time to remain externally to the shape of the points in order to approximate well just the "regular" part. The code is:
clear points
a = 1; b = 0.5;
t = linspace(0, 2*pi,100).';
points(:,1) =10 + a .* cos(t) + 0.1.*(0.5 - rand(100,1));
points(:,2) = 5+b .* sin(t) + 0.1.*(0.5 - rand(100,1));
ellip_x = @(ae, s, x_c) x_c + ae .* cos(s);
ellip_y = @(be, s, y_c) y_c + be .* sin(s);
ellipfun = @(ae,be,s,x_c,y_c) [ellip_x(ae,s,x_c) ellip_y(be,s,y_c)];
xcguess = sum(points(:,1))/length(points);
ycguess = sum(points(:,2))/length(points);
aguess = max(abs(points(:,1)))+ xcguess;
bguess = max(abs(points(:,2)))+ ycguess;
fwrapper = @(x) minNorm(x(1), x(2),x(3),x(4), ellipfun, points);
opts = optimoptions('fmincon','TolX', 1e-8, 'TolFun', 1e-8, 'Display', 'Iter');
%fwrapper([a, b])
extconstr = @(x) constrext(x,ellipfun,points);
xsol = fmincon(fwrapper, [aguess;bguess;xcguess;ycguess], [], [], [], [], [0 0 -Inf -Inf], [], extconstr, opts);
asol = xsol(1); bsol = xsol(2); xcsol = xsol(3); ycsol = xsol(4);
ellipsol = ellipfun(asol, bsol, t,xcsol,ycsol);
axis equal;
plot(points(:,1), points(:,2), '-x');
hold on;
plot(ellipsol(:,1), ellipsol(:,2));
axis equal; grid on;
function normdiff = minNorm(ae,be,x_c,y_c,ellipfun, points)
angvec = nan(length(points), 1);
for j=1:length(points)
angvec(j) = atan2((points(j,2)-y_c) ./ be, (points(j,1)-x_c) ./ ae);
end
ellip_points = ellipfun(ae,be,angvec,x_c,y_c);
normdiff = sum(sum((ellip_points - points).^2, 2));
end
function [C, Ceq] = constrext(x,ellipfun, points)
Ceq = [];
ae = x(1);
be = x(2);
x_c = x(3);
y_c = x(4);
angvec = nan(length(points), 1);
for j=1:length(points)
angvec(j) = atan2((points(j,2)-y_c) ./ be, (points(j,1)-x_c) ./ ae);
end
ellip_points = ellipfun(ae,be,angvec,x_c,y_c);
C = -(sum(ellip_points.^2,2) - sum(points.^2,2));
end
Unfortunally, the result is the following:
Can you tell me, where is the error?
  11 Kommentare
Star Strider
Star Strider am 18 Okt. 2020
Image Analyst — I very much appreciate the reference in your earlier Comment! I wasn’t aware of that one.
Mohammad Mahdi Kariminejad
Mohammad Mahdi Kariminejad am 17 Feb. 2022
Dear colleague, to solve this problem correctly, you should first find and adopt the true functional model, but in many real case studies, the true functional models are not clear for us. In your case, it is far-fetched to fit an ellipse to the whole of the data. However, it seems logical to fit a vertical ellipse to the below section of your data. After that, the correct ellipse fitting is too hard due to your ill-scattered data points as well! You should select a suitable mathematical algorithm similar to the total least square adjustment (maybe alongside the regularization methods) for solving this problem correctly.
Moreover, your initial values play an essential role. By the way, we have used the mentioned algorithm for fitting a circle to the vigorous ill-scattered data points. You can find that in the following link.
https://link.springer.com/article/10.1007/s40328-021-00365-1

Melden Sie sich an, um zu kommentieren.

Antworten (2)

Mathieu NOE
Mathieu NOE am 18 Feb. 2022
hello
I simply used this FEX submission on your data, but removed first the positive y values are they are messing up everything.
result
code
clc
clearvars
warning off
load points.mat
x = points(:,1);
y = points(:,2);
ind = (y>0);
xx = x;
xx(ind) = [];
yy = y;
yy(ind) = [];
figure
plot(x,y,xx,yy);
%% FITELLIPSE : Least squares ellipse fitting demonstration
% Richard Brown, May 28, 2007
% A set of points
x = [xx';
yy'];
% Fit an ellipse using the Bookstein constraint
[zb, ab, bb, alphab] = fitellipse(x, 'linear');
% Fit an ellipse using the Trace constraint
[zt, at, bt, alphat] = fitellipse(x, 'linear', 'constraint', 'trace');
% Plot the results
figure
plot(x(1,:), x(2,:), 'ro')
hold on
axis equal
plotellipse(zb, ab, bb, alphab, 'b--')
plotellipse(zt, at, bt, alphat, 'k--')
legend('Data points', 'Linear Bookstein fit', 'Linear Trace fit')
%% Nonlinear ellipse fitting - minising geometric distance
clf
[zg, ag, bg, alphag] = fitellipse(x);
plot(x(1,:), x(2,:), 'ro')
hold on
axis equal
plotellipse(zb, ab, bb, alphab, 'b--')
plotellipse(zt, at, bt, alphat, 'g--')
plotellipse(zg, ag, bg, alphag, 'k')
legend('Data points', 'Algebraic best fit - Bookstein constraint', ...
'Algebraic best fit - Trace constraint', ...
'Geometric best fit - nonlinear least squares')

Matt J
Matt J am 18 Feb. 2022
Bearbeitet: Matt J am 18 Feb. 2022
If you have the Computer Vision Toolbox, you can do outlier rejection with ransac() in conjunction with any ellipse-fitting routine you wish. Here, I used ellipticalFit() from,
for the ellipse fitting and plotting.
fitFcn=@(points) ellipticalFit(points');
fobj = ransac(data,fitFcn,@distFcn,50,.1,'MaxNumTrials',3000);
plot(fobj);
hold on; scatter(points(:,1),points(:,2),'f'); hold off; shg
axis([-400,400,-300,1000])
function d=distFcn(fobj,points)
t=-fobj.theta;
R = [cosd(t),-sind(t); sind(t),cosd(t)];
Q=R.'*diag(1./fobj.ab.^2)*R;
xy=(points-fobj.center)';
d=abs(sum((Q*xy).*xy)-1)';
end

Kategorien

Mehr zu Get Started with Curve Fitting Toolbox finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by