我获得了三点的位置:
p1 = [1.0, 1.0, 1.0]
p2 = [1.0, 2.0, 1.0]
p3 = [1.0, 1.0, 2.0]
和他们改造的对手:
p1_prime = [2.414213562373094, 5.732050807568877, 0.7320508075688767]
p2_prime = [2.7677669529663684, 6.665063509461097, 0.6650635094610956]
p3_prime = [2.7677669529663675, 5.665063509461096, 1.6650635094610962]
仿射变换矩阵的形式为
trans_mat = np.array([[…, …, …, …],
[…, …, …, …],
[…, …, …, …],
[…, …, …, …]])
这样用
import numpy as np
def transform_pt(point, trans_mat):
a = np.array([point[0], point[1], point[2], 1])
ap = np.dot(a, trans_mat)[:3]
return [ap[0], ap[1], ap[2]]
你会得到:
transform_pt(p1, trans_mat) == p1_prime
transform_pt(p2, trans_mat) == p2_prime
transform_pt(p3, trans_mat) == p3_prime
假设转换是同质的(仅包含旋转和平移),我该如何确定转换矩阵呢?
从CAD程序中,我知道矩阵是:
trans_mat = np.array([[0.866025403784, -0.353553390593, -0.353553390593, 0],
[0.353553390593, 0.933012701892, -0.066987298108, 0],
[0.353553390593, -0.066987298108, 0.933012701892, 0],
[0.841081377402, 5.219578794378, 0.219578794378, 1]])
我想知道如何找到它。
答案 0 :(得分:5)
单独的六个点不足以唯一地确定仿射变换。但是,根据您之前在问题中提出的问题(在删除之前不久)以及your comment,您似乎不仅仅在寻找仿射变换,而是在进行同类仿射变换
This answer by robjohn提供了解决问题的方法。虽然它解决了许多问题的更普遍的问题,但6点的解决方案可以在答案的最底部找到。我将以更加程序员友好的格式将其转录:
import numpy as np
def recover_homogenous_affine_transformation(p, p_prime):
'''
Find the unique homogeneous affine transformation that
maps a set of 3 points to another set of 3 points in 3D
space:
p_prime == np.dot(p, R) + t
where `R` is an unknown rotation matrix, `t` is an unknown
translation vector, and `p` and `p_prime` are the original
and transformed set of points stored as row vectors:
p = np.array((p1, p2, p3))
p_prime = np.array((p1_prime, p2_prime, p3_prime))
The result of this function is an augmented 4-by-4
matrix `A` that represents this affine transformation:
np.column_stack((p_prime, (1, 1, 1))) == \
np.dot(np.column_stack((p, (1, 1, 1))), A)
Source: https://math.stackexchange.com/a/222170 (robjohn)
'''
# construct intermediate matrix
Q = p[1:] - p[0]
Q_prime = p_prime[1:] - p_prime[0]
# calculate rotation matrix
R = np.dot(np.linalg.inv(np.row_stack((Q, np.cross(*Q)))),
np.row_stack((Q_prime, np.cross(*Q_prime))))
# calculate translation vector
t = p_prime[0] - np.dot(p[0], R)
# calculate affine transformation matrix
return np.column_stack((np.row_stack((R, t)),
(0, 0, 0, 1)))
对于您的样本输入,这将恢复与您从CAD程序中获得的完全相同的矩阵:
>>> recover_homogenous_affine_transformation(
np.array(((1.0,1.0,1.0),
(1.0,2.0,1.0),
(1.0,1.0,2.0))),
np.array(((2.4142135623730940, 5.732050807568877, 0.7320508075688767),
(2.7677669529663684, 6.665063509461097, 0.6650635094610956),
(2.7677669529663675, 5.665063509461096, 1.6650635094610962))))
array([[ 0.8660254 , -0.35355339, -0.35355339, 0. ],
[ 0.35355339, 0.9330127 , -0.0669873 , 0. ],
[ 0.35355339, -0.0669873 , 0.9330127 , 0. ],
[ 0.84108138, 5.21957879, 0.21957879, 1. ]])
答案 1 :(得分:2)
找到转换就像解决任何未知的方程组。首先,你必须写下等式,在你的情况下,这意味着你必须知道你正在寻找什么样的转换。例如。刚性平移需要三个参数(x,y和z),因此您必须至少有三个参数。一般旋转需要另外三个参数,这会给你六个未知数。缩放为您提供另外三个参数,总共9个参数。由于你只说了三个点,这就产生了9个unknows,这就是你正在寻找的转变。这意味着你忽略了任何剪切和投射。您应该始终知道要查找的转换类型。
一旦你知道转换的类型,你应该记下矩阵方程,然后求解未知数。这可以通过矩阵乘法用线性代数库完成,例如,通过numpy。
答案 2 :(得分:1)
如果原始数据(p1,p2,p3 i 你的情况)和转换数据(p1_prime,p2_prime,p3_prime),则可以确定转换矩阵 )如下所示:
>>> p # original data
array([[ 1., 1., 1.],
[ 1., 2., 1.],
[ 1., 1., 2.]])
>>> p_prime # transformed data
array([[ 2.41421356, 5.73205081, 0.73205081],
[ 2.76776695, 6.66506351, 0.66506351],
[ 2.76776695, 5.66506351, 1.66506351]])
# Get transformation matrix
>>> trans = np.dot(np.linalg.inv(p),p_prime)
>>> trans # transformation matrix
array([[ 1.70710678, 4.86602541, -0.13397459],
[ 0.35355339, 0.9330127 , -0.0669873 ],
[ 0.35355339, -0.0669873 , 0.9330127 ]])
# obtain transformed data from original data and transformation matrix
>>> np.dot(a, trans)
array([[ 2.41421356, 5.73205081, 0.73205081],
[ 2.76776695, 6.66506351, 0.66506351],
[ 2.76776695, 5.66506351, 1.66506351]])
在您的情况下,由于所有三个点都有一些未知数据转换ap[3]
值,因此无法获得转换矩阵。只有知道这三个值才能获得它。
答案 3 :(得分:0)
此问题称为点对点注册或point-set registration。
对于刚性变换,即忽略剪切和缩放,我喜欢这个tutorial。我参与了寻找质心并应用奇异值分解。
请注意,对于您的特定情况,恰好有三个点,您可以找到一个封闭的表单解决方案。
OpenCV很有帮助。
哦,看看Finding translation and scale on two sets of points to get least square error in their distance?