Как подогнать эллиптический конус к набору данных?

У меня есть набор 3D-данных (300 точек), которые создают поверхность, которая выглядит как два конуса или эллипсоида, соединенные друг с другом. Мне нужен способ найти уравнение наиболее подходящего эллипсоида или конуса для этого набора данных. Метод регрессии не важен, чем он проще, тем лучше. В основном мне нужен способ, код или функция Matlab для вычисления констант эллиптического уравнения для этих данных.


person Ali.J    schedule 04.05.2015    source источник


Ответы (2)


Вы также можете попробовать с fminsearch, но чтобы не попасть в локальные минимумы, вам понадобится хорошая отправная точка, учитывая количество коэффициентов (попробуйте исключить некоторые из них).

Вот пример с 2D-эллипсом:

% implicit equation
fxyc = @(x, y, c_) c_(1)*x.^2 + c_(2).*y.^2 + c_(3)*x.*y + c_(4)*x + c_(5).*y - 1; % free term locked to -1

% solution (ellipse)
c_ = [1, 2, 1, 0, 0]; % x^2, y^2, x*y, x, y (free term is locked to -1)

[X,Y] = meshgrid(-2:0.01:2);
figure(1);
fxy = @(x, y) fxyc(x, y, c_);
c = contour(X, Y, fxy(X, Y), [0, 0], 'b');
axis equal;
grid on;
xlabel('x');
ylabel('y');          
title('solution');          

% we sample the solution to have some data to fit
N = 100; % samples
sample = unique(2 + floor((length(c) - 2)*rand(1, N)));
x = c(1, sample).';
y = c(2, sample).';

x = x + 5e-2*rand(size(x)); % add some noise
y = y + 5e-2*rand(size(y));

fc = @(c_) fxyc(x, y, c_); % function in terms of the coefficients
e = @(c) fc(c).' * fc(c); % squared error function

% we start with a circle
c0 = [1, 1, 0, 0, 0];

copt = fminsearch(e, c0)

figure(2);
plot(x, y, 'rx');
hold on
fxy = @(x, y) fxyc(x, y, copt);
contour(X, Y, fxy(X, Y), [0, 0], 'b');
hold off;
axis equal;
grid on;
legend('data', 'fit');
xlabel('x');                    %# Add an x label
ylabel('y');          
title('fitted solution');

введите здесь описание изображения

person Iban Cereijo    schedule 04.05.2015

Функция Matlab fit может принимать произвольные выражения соответствия. Требуется немного разобраться с параметрами, но это можно сделать.

Сначала вы должны создать объект fittype, содержащий строку, представляющую ожидаемую форму. Вам нужно будет самостоятельно составить выражение, которое лучше всего соответствует вашим ожиданиям, я возьму выражение конуса с сайта Mathworld для примера и переставьте его для z

ft = fittype('sqrt((x^2 + y^2)/c^2) + z_0', ...
     'independent', {'x', 'y'}, 'coeff', {'c', 'z_0'});

Если это простая форма, Matlab может определить, какие переменные и какие коэффициенты, но с чем-то более сложным, как это, вы хотели бы помочь.

Объект 'fitoptions' содержит конфигурацию для методов: в зависимости от вашего набора данных вам, возможно, придется потратить некоторое время на указание верхних и нижних границ, начальных значений и т. д.

fo = fitoptions('Upper', [one, for, each, of, your, coeffs, in, the, order, they, appear, in, the, string], ...
     'Lower', [...], `StartPoint', [...]);

затем получить вывод

[fitted, gof] = fit([xvals, yvals], zvals, ft, fo);

Предупреждение: я много раз делал это с наборами 2D-данных, и в документах указано, что это работает. для трех, но я не делал этого сам, поэтому приведенный выше код может не работать, проверьте документы, чтобы убедиться, что у вас правильный синтаксис.

Возможно, стоит начать с простого выражения соответствия, чего-то линейного, чтобы вы могли заставить свой код работать. Затем замените выражение на конус и поиграйте, пока не получите что-то похожее на то, что вы ожидаете.

После того, как вы получили свою подгонку, хороший трюк заключается в том, что вы можете использовать функцию eval для строкового выражения, которое вы использовали в своей подгонке, чтобы оценить содержимое строки, как если бы это было выражение Matlab. Это означает, что вам нужно иметь переменные рабочей области с теми же именами, что и переменные и коэффициенты в вашем строковом выражении.

person xenoclast    schedule 04.05.2015