【问题标题】:how to perform coordinates affine transformation using python? part 2如何使用python执行坐标仿射变换?第2部分
【发布时间】:2013-12-12 14:28:58
【问题描述】:

我遇到了与此处描述的相同的问题: how to perform coordinates affine transformation using python?

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

primary_system1 = (40.0, 1160.0, 0.0)
primary_system2 = (40.0, 40.0, 0.0)
primary_system3 = (260.0, 40.0, 0.0)
primary_system4 = (260.0, 1160.0, 0.0)

secondary_system1 = (610.0, 560.0, 0.0) 
secondary_system2 = (610.0,-560.0, 0.0) 
secondary_system3 = (390.0, -560.0, 0.0)
secondary_system4 = (390.0, 560.0, 0.0)

执行时出现的错误如下。

*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*

可能是什么问题?

【问题讨论】:

    标签: numpy 3d transformation affinetransform


    【解决方案1】:

    问题是您的矩阵是单数的,这意味着它不可逆。既然你试图取反,那就是个问题。您链接到的线程是您问题的基本解决方案,但它并不是真正的最佳解决方案。您实际想要做的不仅仅是反转矩阵,而是解决最小二乘最小化问题,以找到适合您可能有噪声的数据的最佳仿射变换矩阵。以下是你的做法:

    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
    

    结果

    [[  -1.    0.    0.    0.]
     [   0.    1.    0.    0.]
     [   0.    0.    0.    0.]
     [ 650. -600.    0.    1.]]
    

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

    【讨论】:

    • 这很好用,我强烈推荐!顺便说一句,对于 2D 点,只需添加一个零作为第三个坐标,它仍然有效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多