如何使用python执行坐标仿射变换?第2部分 [英] how to perform coordinates affine transformation using python? part 2

查看:20
本文介绍了如何使用python执行坐标仿射变换?第2部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了与此处描述的相同的问题:如何使用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)次要系统 1 = (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(最近一次调用最后一次):文件affine_try.py",第 57 行,在 <module> 中次要系统3、次要系统4)文件affine_try.py",第 22 行,在 solve_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行,invreturn wrap(solve(a, identity(a.shape[0], dtype=a.dtype)))文件/usr/lib/python2.7/dist-packages/numpy/linalg/linalg.py",第328行,在解决引发 LinAlgError, '奇异矩阵'numpy.linalg.linalg.LinAlgError:奇异矩阵*

可能是什么问题?

解决方案

问题是你的矩阵是奇异的,这意味着它不可逆.因为你试图取反,这是一个问题.您链接到的线程是您问题的基本解决方案,但它并不是真正的最佳解决方案.您实际想要做的不仅仅是反转矩阵,而是解决最小二乘最小化问题,以便为可能存在噪声的数据找到最佳仿射变换矩阵.这样做的方法如下:

将 numpy 导入为 np主要 = np.array([[40., 1160., 0.],[40., 40., 0.],[260., 40., 0.],[260., 1160., 0.]])次要 = np.array([[610., 560., 0.],[610., -560., 0.],[390., -560., 0.],[390., 560., 0.]])# 用一个填充数据,这样我们的转换也可以做翻译n =primary.shape[0]pad = lambda x: np.hstack([x, np.ones((x.shape[0], 1))])unpad = lambda x: x[:,:-1]X = 垫(主要)Y = 垫(次要)# 解决最小二乘问题 X * A = Y# 找到我们的变换矩阵AA, res, rank, s = np.linalg.lstsq(X, Y)变换 = lambda x: unpad(np.dot(pad(x), A))打印目标:"印刷二级打印结果:"打印转换(主要)打印最大误差:",np.abs(secondary - transform(primary)).max()

您的原始矩阵是奇异矩阵的原因是您的第三个坐标始终为零,因此无法确定该坐标上的变换应该是什么(零乘以任何值都为零,因此任何值都可以工作).

>

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

A[np.abs(A) <1e-10] = 0 # 将非常小的值设置为零打印 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 是新系统中的坐标.如您所见,最小二乘法只是将与第三维相关的所有项设置为零,因为您的系统实际上是二维的.

I have same problem as described here: how to perform coordinates affine transformation using python?

I was trying to use method described but some reason I will get error messages. Changes I made to code was to replace primary system and secondary system points. I created secondary coordinate points by using different origo. In real case for which I am studying this topic will have some errors when measuring the coordinates.

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)

Error I get from when executing is following.

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

What might be the problem ?

解决方案

The problem is that your matrix is singular, meaning it's not invertible. Since you're trying to take the inverse of it, that's a problem. The thread that you linked to is a basic solution to your problem, but it's not really the best solution. Rather than just inverting the matrix, what you actually want to do is solve a least-squares minimization problem to find the optimal affine transform matrix for your possibly noisy data. Here's how you would do that:

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()

The reason that your original matrix was singular is that your third coordinate is always zero, so there's no way to tell what the transform on that coordinate should be (zero times anything gives zero, so any value would work).

Printing the value of A tells you the transformation that least-squares has found:

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

results in

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

which is equivalent to x2 = -x1 + 650, y2 = y1 - 600, z2 = 0 where x1, y1, z1 are the coordinates in your original system and x2, y2, z2 are the coordinates in your new system. As you can see, least-squares just set all the terms related to the third dimension to zero, since your system is really two-dimensional.

这篇关于如何使用python执行坐标仿射变换?第2部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆