Одинаково разнесенная оценка сплайнов в scipy - PullRequest
0 голосов
/ 26 сентября 2018

Я использую scipy для построения двумерного сплайна кривой (аналогично эллипсу) с splprep и splev.Цель состоит в том, чтобы сгладить точки.

Проблема в том, что точки, которые я пытаюсь сгладить, неравномерно распределены по траектории, и когда я пытаюсь оценить сплайн, я получу неравномерное распределение, но яхотел бы иметь равномерно распределенные точки на сплайне.

Вот пример, показывающий, как выглядят мои данные, и аналогичный результат (в моем случае этот эффект, на самом деле, гораздо более очевиден):

t = np.r_[0:2*np.pi:100.j, 0.142:np.pi+0.1:100j, 0.07+np.pi/2:0.23+np.pi:200j]
t = np.random.normal(t, 0.01)
t = np.unique(t)
# plt.plot(t)
r = np.asarray([1.0, 1.01] * (len(t) // 2)) # np.random.normal() # 1, 0.005, size=len(t))
xy = np.asarray([np.cos(t) * r, np.sin(t) * r]).T
# plt.plot(*xy.T, '.')
# plt.axis('equal')

tck, _ = splprep(xy.T, s=0, per=True)
xi, yi = splev(np.linspace(0, 1, 200), tck)
plt.subplots(figsize=(10, 10))
plt.plot(xi, yi, '.')
plt.axis('equal')

Как видно из графика ниже, есть одна область, которая является более плотной из точек: я хотел бы избежать этого эффекта и иметь равномерно распределенные точки (даже лучше, если они расположены с фиксированным углом относительнок центроиду, например, 1 балл каждые 0,5 градуса).

Non uniform distribution of points after spline eval

Я думаю, что причина этого заключается в том, что точки приводят к «зубчатому» шаблону вплотная область: см., например, этот график, показывающий, как точки меняются по частоте в верхней части круга.

Jagged edges

Я думаю, что это связано счасау u вычисляется в splprep ( см. документ) , и я думаю, что я мог бы решить эту проблему, настроив параметр u, но я не знаю, как: способ вычисленияочевидно, сейчас все в порядке, и я не могу придумать лучшую стратегию:

v = [0]
for i in range(1, len(xy)):
    vi = v[i - 1] + sum((xy[i] - xy[i - 1]) ** 2) ** 0.5
    v.append(vi)
u = [v[i] / v[-1] for i in range(1, len(xy))]

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

Как мне сгладить процесс создания данныхВы уверены, что оцененные точки на сплайне находятся примерно на одном и том же расстоянии друг от друга?

Редактировать

Я понял, что мне нужно установить u как угол каждой точки (разделенныйна 2pi, чтобы нормализовать в пределах 0 и 1).Я пробовал, и точки выглядят равномерно, но по некоторым причинам я получаю некоторые выбросы

uu = t / (2 * np.pi) # u1# 2
tck, _ = splprep(xy.T, u=uu, s=0, per=True)
xi, yi = splev(np.linspace(0, 1, 200), tck)
plt.subplots(figsize=(10, 10))
plt.plot(xi, yi)#, '.')
plt.axis('equal')

Outliers after changing U

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

1 Ответ

0 голосов
/ 27 сентября 2018

Форсирование u=t усложняет жизнь интерполятору, поскольку некоторые значения t очень близки друг к другу, в то время как соответствующие точки не так близки из-за изменяющегося r.Это приводит к большим отклонениям интерполяционной кривой от данных, т. Е. Выбросам на втором графике.

Вместо этого вычислите сплайн со значением по умолчанию u, а затем выполните повторную параметризацию пропорционально полярному углу.Для этого я сначала оцениваю сплайн на равных расстояниях в области параметров (как в вашей первой попытке), нахожу полярный угол каждой результирующей точки с помощью unwrap(arctan2), а затем нахожу обратную функцию u-> angleс линейной интерполяцией.Эта обратная функция, вставленная в сплайн, приводит к равномерно расположенным точкам в соответствии с их полярным углом.

xx, yy = splev(np.linspace(0, 1, 200), tck)
s = np.unwrap(np.arctan2(yy, xx))
s_inv = np.interp(np.linspace(s[0], s[-1], len(s)), s, np.linspace(0, 1, len(s))) 
xi, yi = splev(s_inv, tck)

better

...