Подтвердить что ты не робот

Поиск кривизны из шумного набора точек данных с использованием 2d/3dsplines? (С++)

Я пытаюсь извлечь кривизну импульса вдоль его профиля (см. рисунок ниже). Импульс рассчитывается по сетке длины и высоты: 150 x 100 ячеек с использованием Finite Differences, реализованных на С++.

Pulse profile with varying curvature

Я извлек все точки с тем же значением (набор контуров/уровней) и отметил их как красную сплошную линию на рисунке ниже. Другие цвета незначительны.

red line = dataset of points with the same value

Затем я попытался найти кривизну из этой уже шумной (из-за решетки) контурной линии следующими способами:

(уже скорректированная скользящая средняя)

1) Кривизна через тангенсы
Curvature Approximation from two Points P and N

Кривизна линии в точке P определяется следующим образом:

tangents of 2 points = curvature at one point

Таким образом, кривизна - это лаймы угла треугольника по длине дуги между P и N. Поскольку мои точки имеют определенное расстояние между ними, я не мог достаточно приблизить лаймы, чтобы кривизна не была рассчитана правильно. Я проверил его с кругом, который, естественно, имеет постоянную кривизну. Но я не смог воспроизвести это (только 1 значащая цифра была правильной).

2) Вторая производная от строки, параметризованной arclength

Я вычислил первую производную линии по длине дуги, сглаженную скользящим средним, а затем снова взял производную (2-я производная). Но здесь я также получил только 1 значащую цифру. К сожалению, взятие производной умножает уже присущий шум на более крупные уровни.

3) Приближение линии локально с кружком

Поскольку обратный радиус окружности - это кривизна, я использовал следующий подход:

Approximating the curvature with a circle

Это работало лучше всего (2 правильных значащих цифры), но мне нужно уточнить еще больше. Итак, моя новая идея такова:

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

До сих пор я не мог найти библиотеку С++, которая может генерировать такую ​​поверхность сплайна Безье. Могли бы вы, возможно, указать мне на кого-нибудь?

И как вы думаете, этот подход стоит сделать, или я потеряю слишком большую точность в своей кривизне?

Знаете ли вы какой-либо другой подход?

С очень любезными пожеланиями, Ян

edit: Кажется, я не могу опубликовать фотографии как новый пользователь, поэтому я удалил их все из своего вопроса, хотя я считаю их важными для объяснения моей проблемы. Есть ли способ показать их?

edit2: ok, done:)

4b9b3361

Ответ 1

Существует ALGLIB, который поддерживает различные варианты интерполяции:

  • Полиномиальная интерполяция
  • Рациональная интерполяция
  • Сплийн-интерполяция
  • Фиксация наименьших квадратов (линейная/нелинейная)
  • Билинейная и бикубическая сплайн-интерполяция
  • Быстрая интерполяция/подстановка RBF

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

Чтобы предотвратить перенасыщение ваших шумовых входных точек, вы должны применить какой-то механизм сглаживания, например. вы можете попробовать, если применимы такие вещи, как Moving Window Average/Gaussian/FIR. Также посмотрите на (Cubic) сглаживающие сплайны.