Numpy 如何使用python执行坐标仿射变换?第二部分

Numpy 如何使用python执行坐标仿射变换?第二部分,numpy,3d,transformation,affinetransform,Numpy,3d,Transformation,Affinetransform,我的问题与这里描述的相同: 我试图使用描述的方法,但由于某些原因,我会收到错误消息。 我对代码所做的更改是替换主系统和辅助系统点。我使用不同的origo创建了次坐标点。在我正在研究的实际案例中,当测量坐标时,这个主题会有一些误差 执行以下操作时我从中得到的错误 *Traceback (most recent call last): File "affine_try.py", line 57, in <module> secondary_system3, secondar

我的问题与这里描述的相同:

我试图使用描述的方法,但由于某些原因,我会收到错误消息。 我对代码所做的更改是替换主系统和辅助系统点。我使用不同的origo创建了次坐标点。在我正在研究的实际案例中,当测量坐标时,这个主题会有一些误差

执行以下操作时我从中得到的错误

*Traceback (most recent call last):
  File "affine_try.py", line 57, in <module>
    secondary_system3, secondary_system4 )
  File "affine_try.py", line 22, in solve_affine
    A2 = y * x.I
  File "/usr/lib/python2.7/dist-packages/numpy/matrixlib/defmatrix.py", line 850, in getI
    return asmatrix(func(self))
  File "/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py", line 445, in inv
    return wrap(solve(a, identity(a.shape[0], dtype=a.dtype)))
  File "/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py", line 328, in solve
    raise LinAlgError, 'Singular matrix'
numpy.linalg.linalg.LinAlgError: Singular matrix*
*回溯(最近一次呼叫最后一次):
文件“affine_try.py”,第57行,在
辅助系统3、辅助系统4)
文件“affine\u try.py”,第22行,在solve\u affine中
A2=y*x.I
文件“/usr/lib/python2.7/dist packages/numpy/matrixlib/defmatrix.py”,第850行,在getI中
返回asmatrix(func(self))
文件“/usr/lib/python2.7/dist packages/numpy/linalg/linalg.py”,第445行,在inv中
返回换行符(求解(a,标识(a.shape[0],dtype=a.dtype)))
文件“/usr/lib/python2.7/dist packages/numpy/linalg/linalg.py”,第328行,在solve中
提高线性误差,“奇异矩阵”
numpy.linalg.linalg.linalgeror:奇异矩阵*

可能有什么问题?

问题是矩阵是单数的,这意味着它是不可逆的。既然你想取相反的结果,那就是个问题。您链接到的线程是问题的基本解决方案,但它并不是最佳解决方案。实际上,您要做的不是反转矩阵,而是解决最小二乘最小化问题,为可能有噪声的数据找到最佳仿射变换矩阵。以下是您将如何做到这一点:

import numpy as np

primary = np.array([[40., 1160., 0.],
                    [40., 40., 0.],
                    [260., 40., 0.],
                    [260., 1160., 0.]])

secondary = np.array([[610., 560., 0.],
                      [610., -560., 0.],
                      [390., -560., 0.],
                      [390., 560., 0.]])

# Pad the data with ones, so that our transformation can do translations too
n = primary.shape[0]
pad = lambda x: np.hstack([x, np.ones((x.shape[0], 1))])
unpad = lambda x: x[:,:-1]
X = pad(primary)
Y = pad(secondary)

# Solve the least squares problem X * A = Y
# to find our transformation matrix A
A, res, rank, s = np.linalg.lstsq(X, Y)

transform = lambda x: unpad(np.dot(pad(x), A))

print "Target:"
print secondary
print "Result:"
print transform(primary)
print "Max error:", np.abs(secondary - transform(primary)).max()
原始矩阵奇异的原因是,第三个坐标始终为零,因此无法确定该坐标上的变换应该是什么(零乘以任何值都等于零,所以任何值都有效)

打印
A
的值告诉您最小二乘法找到的变换:

A[np.abs(A) < 1e-10] = 0  # set really small values to zero
print A

这相当于
x2=-x1+650,y2=y1-600,z2=0
其中
x1,y1,z1
是原始系统中的坐标,
x2,y2,z2
是新系统中的坐标。正如您所见,最小二乘法只是将所有与第三维相关的项设置为零,因为您的系统实际上是二维的。

我强烈建议您这样做非常有效!顺便说一句,对于二维点,只需添加一个零作为第三个坐标,它仍然有效
A[np.abs(A) < 1e-10] = 0  # set really small values to zero
print A
[[  -1.    0.    0.    0.]
 [   0.    1.    0.    0.]
 [   0.    0.    0.    0.]
 [ 650. -600.    0.    1.]]