У меня есть два набора точек (x,y)
, которые я построил с помощью matplotlib.
Просто визуально я вижу, что между ними есть какая-то ротация.
Я хотел бы повернуть один набор точек вокруг определенной точки (хотел бы попробовать несколько точек вращения) и снова построить их.
Как лучше всего повернуть указанный набор точек с помощью python?
Я читал, что, возможно, можно использовать shapely, но простой пример поможет мне понять, как это сделать.
Чтобы найти наилучшее преобразование между двумя облаками точек, одним из способов является использование алгоритма Iterative Closest Point . Например, используя open3d.registration.registration_icp
Один важный вопрос: вы уже знаете, какая точка из первого набора должна быть сопоставлена с какой точкой второго набора? То есть, у вас есть точки A, B, C, D в первом наборе и A', B', C', D' во втором наборе, и вы хотите найти вращение, которое отображает A в A', B в B', C к C', D к D' и т.д.? Или у вас есть точки A, B, C, D в первом наборе и точки E, F, G, H во втором наборе, и вы не знаете, соответствует ли A E, F, G или H?
@Stef К сожалению, две строки не имеют соответствия 1-1. На самом деле, повернув их, я хотел бы увидеть, насколько они разные.
В общем, если вы не знаете соответствие или нет точного соответствия, ICP (итеративная ближайшая точка) может быть простым алгоритмом, который может работать. Но если вы уже знаете, что ваши облака точек представляют определенную форму, например линию, то, возможно, будет лучше найти преобразование, работая с представлением формы, а не с облаками точек. Возможно, RanSaC (консенсус случайной выборки) может быть полезен.
@Stef ICP кажется действительно интересным. Завтра я попытаюсь найти простой пример этого, чтобы попробовать.
Используйте numpy для хранения ваших очков
Например, если у вас есть массив nx2, каждая строка которого представляет собой точку, например
xy=np.array([[50, 60],
[10, 30],
[30, 10]])
Вы можете построить их так
plt.scatter(xy[:,0], xy[:,1])
А чтобы их повернуть, нужна матрица вращения
def rotateMatrix(a):
return np.array([[np.cos(a), -np.sin(a)], [np.sin(a), np.cos(a)]])
Вы можете применить эту матрицу к своему xy
набору очков, подобному этому
newxy = xy @ rotateMatrix(a).T
Обратите внимание, что я транспонирую матрицу вращения, чтобы сохранить точность. Но в этом случае из-за особой формы матрицы поворота вы можете сгенерировать непосредственно транспонированную матрицу, просто передав -a
newxy = xy @ rotateMatrix(-a)
Если вам не нужно вращать вокруг центра (x0,y0), отличного от (0,0), просто поверните не xy, а xy-(x0,y0) (то есть вектор смещения от центра к точкам), а затем добавьте это повернутое вектор к центру.
newxy = (xy-[x0,y0]) @ rotateMatrix(-a) + [x0,y0]
заявка
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib
import time
def rotateMatrix(a):
return np.array([[np.cos(a), -np.sin(a)], [np.sin(a), np.cos(a)]])
xy=np.random.randint(0,100, (200,2))
fig=plt.figure()
plt.plot(xy[:,0], xy[:,1], 'o')
plt.xlim(-30,130)
plt.ylim(-50,110)
plotdata,=plt.plot(xy[:,0], xy[:,1],'o')
x0=20
y0=50
def anim(i):
newxy=(xy-[x0,y0]) @ rotateMatrix(-2*i*np.pi/180) + [x0,y0]
plotdata.set_data(newxy[:,0], newxy[:,1])
return [plotdata]
theAnim=animation.FuncAnimation(fig, anim, interval=40, blit=False, frames=360, repeat=False)
#theAnim.save('rotate.nosync.gif')
plt.show()
Спасибо!. Быстрый вопрос. Это вращает точки вокруг (0,0), верно? Есть ли способ включить вращение вокруг другой точки? Я полагаю, что матрица вращения также должна включать эту информацию...
@KansaiRobot Либо в матрице вращения. Но это означает наличие матрицы вращения 3x3 в однородных координатах, а также списка точек n×3 xy1. В вашем случае самый простой способ, вероятно, просто удалить центр из xy перед вращением и добавить его обратно после вращения. Я редактирую свой ответ соответственно
Обратите внимание, что «применить заданный поворот к заданному облаку точек» и «найти поворот, который лучше всего отображает заданное облако точек в другое заданное облако точек» — это две разные задачи.