tundramani
@tundramani

Как реализовать распознавание кривых на canvas?

подскажите как такое сделать и где подсмотреть готовый алгоритм или готовую библиотеку

сначала пользователь двигает пальцем по канвасу и в результате мы получаем массив точек - это верхняя картинка

надо разбить это на фрагменты которые можно описать кубическими кривыми безье
то есть такими которые описывают кривизну отрезка кривой между двумя точками по двум точкам вне этой кривой

в данном примере получилось два фрагмента
начальная и конечная точки известны изначально
вычислена точка средняя и четыре точки для описаниы кривизны:

6054dc4fc61d6287695790.jpeg
  • Вопрос задан
  • 207 просмотров
Решения вопроса 1
tundramani
@tundramani Автор вопроса
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
wataru
@wataru Куратор тега Алгоритмы
Разработчик на С++, экс-олимпиадник.
Готовых решений я не знаю, но есть следующие идеи.

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

Составим функцию ошибки f(x1, y1, x2, y2) = (X(i/n)-x_i)^2+(Y(i/n)-y_i)^2. Тут x_i, y_i - координаты i-ого пикселя в нарисованной кривой, пронумерованные от 0 до n, X(t), Y(t) - координаты точки на кривой Безье - линейные комбинации x1, x2 и y1, y2 с известными вычисляемыми от t коэффициентами. Это фактически сумма квадратов расстояний от каждого пикселя до неизвестной кривой. Ее можно минимизировать подобно методу наименьших квадратов - считайте производную по всем переменным, приравнивайте к 0. Получите 4 неизвестные и 4 линейных уравнения. Можно вообще на бумажке руками методом Краммера решить, а можно алгоритмом Гаусса подсчитать.

Тут есть допущение, что i-ый пиксель будет аппроксимироваться t=i/n точкой на кривой. Вообще говоря, это не гарантированно, но в качестве некой грубой меры оптимальности подойдет. Может вообще отлично работать будет и так, я не знаю. Поэксперементируйте. Но еще можно потом честно искать ближайшую точку на кривой к заданному пикселю как оптимум полинома 6-ей степени от t, когда все опорные точки кривой фиксированы. Тут надо брать производную, находить ее нули и среди них брать лучшее t. Чтобы найти нули полинома 5-ой степени можно рекурсивно брать производную, находить нули полинома меньшей степени, и потом на каждом монотонном отрезке искать пересечение с OX бинарным поиском. Или использовать метод Ньютона. Это давно решенная задача - должно быть куча готовых решений.

Когда вы так научились считать расстояние от кучки пикселей до кривой Безье, можно локально градиентным спуском по 4-м координатам x1, x2, y1, y2 улучшать эту правильную метрику с оптимума полученного грубой метрикой.

Вот мы и умеем аппроксимировать кучку пикселей одной кривой. Заодно мы получаем метрику близости кривой к пикселям. Но надо сделать ее не зависящей от длины - поэтому складывайте квадраты расстояний и делите на количество пикселей.

А дальше алгоритм прост - жадно откусывайте от вашего массива пикселей самые длинные куски, которые хорошо аппроксимируются кривой (дают маленькую метрику). Для этого можно тупо перебирать сколько пикселей отдаем первой кривой, считать метрику и, если она слишком плохая, то останавливаться. Можно чем-то вроде бинарного поиска тут делать - увеличиваете длину куска в 2 раза, пока метрика не станет плохой, а потом гоните бинарный поиск, ища самое большое значение количество пикселей, которое еще дает хорошую метрику. (тут используется предположение, что чем короче пиксельная кривая, тем легче ее аппроксимировать).

Это эмпирический алгоритм и он много где жадный. Нет никакой гарантии, что он даст математически оптимальный результат, но есть много шансов, что он даст достаточно хороший результат.
Ответ написан
Если нужен алгоритм, то читать описание здесь.
Если реализация, тогда potrace.sourceforge.net
Ответ написан
Комментировать
Первое что пришло на ум - поиск экстремумов кривой. В этом случае n следующих друг за другом точки экстремума - опорные точки. Далее предполагаю, что кривая безье описывается параметрическим уравнением и можно имея n опорных точек и множество точек на кривой найти остальные опорные точки. Вероятнее всего нужно решать систему уравнений.

Саму траекторию легко вычислить генетическим алгоритмом. Он медленый но простой в реализации.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы