如何将通过xy相机坐标捕捉到的扭曲正方形转换为cm坐标中的完美正方形



我很抱歉问了一个问题,如果你知道如何解决这个问题,并且以前问过很多版本的同一个问题的话,这个问题可能很容易。然而,我正在创建一个新的帖子,因为我还没有找到这个特定问题的答案。

基本上,我有一个200厘米x 200厘米的正方形,我正在上面用相机录制。然而,相机会稍微扭曲正方形,见这里的例子。。我想知道如何将相机中的x,y坐标转换为真实的x,y坐标(例如,每侧在0-200厘米之间(。我知道我可能需要应用某种变换矩阵,但我不知道是哪一种,也不知道如何确定变换矩阵。我已经很长时间没有做过任何严肃的线性代数了,所以我很感激任何关于阅读内容或如何完成的指导。我在python中工作,所以如果有一些现成的代码可以进行转换,那么了解一下也会很有用。

非常感谢!

我将使用python和numpy来展示这一点。

import numpy as np

首先,你必须了解投影模型

def apply_homography(H, p1):
p = H @ p1.T
return (p[:2] / p[2]).T

通过一些代数运算,可以确定平面z=1上产生给定点的点。

def revert_homography(H, p2):
Hb = np.linalg.inv(H)
# 1 figure out which z coordinate should be added to p2 
# order to get z=1 for p1
z = 1/(Hb[2,2] + (Hb[2,0] * p2[:,0] + Hb[2,1]*p2[:,1]))
p2 = np.hstack([p2[:,:2] * z[:,None], z[:, None]])
return p2 @ Hb.T

投影是不可逆的,但在互补性假设下,它可以成功地反转。

现在,让我们看看如何从给定点(假设它们共面(确定H矩阵。

如果你把四个角按顺序排列,你可以简单地指定角的(x,y(坐标,然后你可以使用投影方程来确定单应矩阵,比如这里,或者这里。

这需要至少确定5个点,因为有9个系数,但我们可以固定矩阵的一个元素,使其成为非齐次方程。

def find_homography(p1, p2):
A = np.zeros((8, 2*len(p1)))
# x2'*(H[2,0]*x1+H[2,1]*x2)
A[6,0::2] = p1[:,0] * p2[:,0]
A[7,0::2] = p1[:,1] * p2[:,0]
# - (H[0,0]*x1+H[0,1]*y1+H[0,2])
A[0,0::2] = -p1[:,0] 
A[1,0::2] = -p1[:,1]
A[2,0::2] = -1

# y2'*(H[2,0]*x1+H[2,1]*x2)
A[6,1::2] = p1[:,0] * p2[:,1]
A[7,1::2] = p1[:,1] * p2[:,1]
# - (H[1,0]*x1+H[1,1]*y1+H[1,2])
A[3,1::2] = -p1[:,0]
A[4,1::2] = -p1[:,1]
A[5,1::2] = -1

# assuming H[2,2] = 1 we can pass its coefficient
# to the independent term making an inhomogeneous
# equation
b = np.zeros(2*len(p2))
b[0::2] = -p2[:,0]
b[1::2] = -p2[:,1]
h = np.ones(9)
h[:8] = np.linalg.lstsq(A.T, b, rcond=None)[0]
return h.reshape(3,3)

这里是一个完整的用法示例。我选取一个随机的H,变换四个随机点,这就是你所拥有的,我展示了如何找到变换矩阵H_。接下来,我创建一个测试点集,并展示如何从图像坐标中找到世界坐标。

# Pick a random Homography
H = np.random.rand(3,3)
H[2,2] = 1
# Pick a set of random points
p1 = np.random.randn(4, 3);
p1[:,2] = 1;
# The coordinates of the points in the image
p2 = apply_homography(H, p1)

# testing
# Create a set of random points
p_test = np.random.randn(20, 3)
p_test[:,2] = 1;
p_test2 = apply_homography(H, p_test)
# Now using only the corners find the homography
# Find a homography transform
H_ = find_homography(p1, p2)
assert np.allclose(H, H_)
# Predict the plane points for the test points
p_test_predicted = revert_homography(H_, p_test2)
assert np.allclose(p_test_predicted, p_test)

最新更新