Как я могу подогнать кривую Безье к набору данных?

У меня есть набор точек данных (которые я могу искривить), которые мне нужны, чтобы соответствовать NumPy).

Я прочитал несколько исследовательских работ, но ни один из них не имеет достаточно подробностей, чтобы полностью реализовать. Есть ли примеры с открытым исходным кодом?

Ответ 1

У меня есть аналогичная проблема, и я нашел "Алгоритм автоматического подбора оцифрованных кривых" из Graphics Gems (1990) о подгонке кривой Безье. Кроме того, я нашел исходный код для этой статьи.

К сожалению, это написано на языке C, который я не очень хорошо знаю. Кроме того, алгоритм довольно трудно понять (по крайней мере для меня). Я пытаюсь перевести его в код С#. Если я добьюсь успеха, я попытаюсь поделиться им.

Файл GGVecLib.c в той же папке, что и FitCurves.c, содержит функции управления основными векторами.

Я нашел аналогичный вопрос Stack Overflow, Сглаживание рисованной кривой. Утвержденный ответ предоставляет код С# для алгоритма подбора кривой из графических самоцветов.

Ответ 2

Чего не хватает во многих из этих ответов, так это в том, что вы, возможно, не захотите подгонять к своим данным одну кубическую кривую Безье. В более общем смысле, вы хотели бы подогнать последовательность произвольных кубических кривых Безье, то есть кусочно кубическую подгонку Безье, к произвольному набору данных.

Есть хороший тезис, датированный 1995 годом, в комплекте с кодом MATLAB, который делает это:

% Lane, Edward J. Fitting Data Using Piecewise G1 Cubic Bezier Curves.
% Thesis, NAVAL POSTGRADUATE SCHOOL MONTEREY CA, 1995

http://www.dtic.mil/dtic/tr/fulltext/u2/a298091.pdf

Чтобы использовать это, вы должны, как минимум, указать количество точек узла, т.е. число точек данных, которые будут использоваться подпрограммами оптимизации для подбора. При желании вы можете сами указать точки узлов, что повышает надежность посадки. Тезис показывает несколько довольно жестких примеров. Отметим, что подход Лейна гарантирует непрерывность G1 (направления смежных касательных векторов идентичны) между кубическими сегментами Безье, т.е. гладкими соединениями. Однако могут быть разрывы в кривизне (изменения в направлении второй производной).

Я переопределил код, обновив его до современного MATLAB (R2015b). Свяжитесь со мной, если хотите.

Вот пример использования всего лишь трех узловых точек (выбираемых автоматически кодом) для подгонки двух кубических сегментов Безье к фигуре Лиссажу.

Lissajous figure

Ответ 3

Вы можете настроить проблему как наименьшее квадратное значение, соответствующее шумовым данным.

См. http://nbviewer.ipython.org/5688579

Обратите внимание, что как только вы выясните уравнения, фактическое вычисление достаточно просто. Фактические вычисления суммируются по данным, а затем инвертируют и умножают матрицу 4x4.

Я знаю, что эта нить уже давно мертва, но я обнаружил, что это интересная проблема, если кто-то еще наткнется на нее.

Смотрите http://www.embedded.com/electrical-engineer-community/industry-blog/4027019/1/Why-all-the-math- за отличный учебник по наименьшим квадратам.

Ответ 4

Если большая часть данных соответствует модели, вы можете попробовать RANSAC. Было бы достаточно легко выбрать 4 балла и случайные и подогнать кривую Безье. Я не уверен в том, насколько дорого стоить оценка кривой против всех остальных точек (часть алгоритма RANSAC). Но это было бы линейное решение, и RANSAC действительно легко писать (и, вероятно, есть алгоритмы с открытым исходным кодом).

Ответ 5

Прежде всего, убедитесь, что вы просите, на самом деле то, что вы хотите. Установка точек на кривую Безье поместит их в корпус точек. Использование сплайна гарантирует, что ваша кривая пройдет через все точки.

Тем не менее, создание функции, которая рисует либо вообще не сложно. В Википедии есть хорошая статья, которая объяснит основы, кривая Безье.

Ответ 6

У меня было решение MATLAB для этой проблемы. Я столкнулся с той же проблемой, но мой код написан в MATLAB. Я надеюсь, что его не слишком сложно перевести на Python.

Вы можете найти контрольные точки по этому коду FindBezierControlPointsND.m По какой-то причине он не имеет функции "ChordLengthNormND" в своем архиве, но он вызывается в строке 45.

Я заменил его следующими строками:

[arclen,seglen] = arclength(p(:,1),p(:,2),'sp');
t = zeros(size(p,1),1);
sums = seglen(1);
for i = 2:size(p,1)-1
    t(i) = sums / arclen;
    sums = sums + seglen(i);
end
t(end) = 1;

arclength Здесь можно получить код MATLAB.

После этого у нас есть контрольные точки для кривой Безье, и есть много вариантов построения кривой Безье с помощью контрольных точек в Интернете.