Sto provando ad implementare il cerchio dei minimi quadrati che segue il documento this (scusate non posso pubblicarlo). La carta afferma che possiamo adattare un cerchio calcolando l'errore geometrico come la distanza euclidea (Xi '') tra un punto specifico (Xi) e il punto corrispondente sul cerchio (Xi '). Abbiamo tre parametri: Xc (un vettore di coordinate del centro del cerchio) e R (raggio).Raccordo circolare dei minimi quadrati usando MATLAB Optimization Toolbox
mi si avvicinò con il seguente codice MATLAB (notare che io sto cercando di adattare i cerchi, non sfere come è indicato sulle immagini):
function [ circle ] = fit_circle(X)
% Kör paraméterstruktúra inicializálása
% R - kör sugara
% Xc - kör középpontja
circle.R = NaN;
circle.Xc = [ NaN; NaN ];
% Kezdeti illesztés
% A köz középpontja legyen a súlypont
% A sugara legyen az átlagos négyzetes távolság a középponttól
circle.Xc = mean(X);
d = bsxfun(@minus, X, circle.Xc);
circle.R = mean(bsxfun(@hypot, d(:,1), d(:,2)));
circle.Xc = circle.Xc(1:2)+random('norm', 0, 1, size(circle.Xc));
% Optimalizáció
options = optimset('Jacobian', 'on');
out = lsqnonlin(@ort_error, [circle.Xc(1), circle.Xc(2), circle.R], [], [], options, X);
end
%% Cost function
function [ error, J ] = ort_error(P, X)
%% Calculate error
R = P(3);
a = P(1);
b = P(2);
d = bsxfun(@minus, X, P(1:2)); % X - Xc
n = bsxfun(@hypot, d(:,1), d(:,2)); % || X - Xc ||
res = d - R * bsxfun(@times,d,1./n);
error = zeros(2*size(X,1), 1);
error(1:2:2*size(X,1)) = res(:,1);
error(2:2:2*size(X,1)) = res(:,2);
%% Jacobian
xdR = d(:,1)./n;
ydR = d(:,2)./n;
xdx = bsxfun(@plus,-R./n+(d(:,1).^2*R)./n.^3,1);
ydy = bsxfun(@plus,-R./n+(d(:,2).^2*R)./n.^3,1);
xdy = (d(:,1).*d(:,2)*R)./n.^3;
ydx = xdy;
J = zeros(2*size(X,1), 3);
J(1:2:2*size(X,1),:) = [ xdR, xdx, xdy ];
J(2:2:2*size(X,1),:) = [ ydR, ydx, ydy ];
end
Il raccordo però non è troppo buono: se inizio con il buon vettore di parametri, l'algoritmo termina al primo passo (quindi c'è un minimo locale dove dovrebbe essere), ma se perturba il punto di partenza (con un cerchio senza rumore) il raccordo si ferma con errori molto grandi. Sono sicuro di aver trascurato qualcosa nella mia implementazione.