【问题标题】:Camera motion from corresponding images来自相应图像的相机运动
【发布时间】:2013-05-14 09:30:48
【问题描述】:

我正在尝试根据相应图像的运动来计算新的相机位置。 图像符合针孔相机模型。

事实上,我没有得到有用的结果,所以我尝试描述我的过程,希望有人可以帮助我。

我用SIFT匹配对应图像的特征,用OpenCV的FlannBasedMatcher匹配它们,用OpenCV的findFundamentalMat(方法RANSAC)计算基本矩阵。

然后我通过相机内在矩阵(K)计算本质矩阵:

Mat E = K.t() * F * K;

我用奇异值分解将本质矩阵分解为旋转和平移:

SVD decomp = SVD(E);
Matx33d W(0,-1,0,
          1,0,0,
          0,0,1);
Matx33d Wt(0,1,0,
          -1,0,0,
           0,0,1);
R1 = decomp.u * Mat(W) * decomp.vt;
R2 = decomp.u * Mat(Wt) * decomp.vt;
t1 = decomp.u.col(2); //u3
t2 = -decomp.u.col(2); //u3

然后我尝试通过三角测量找到正确的解决方案。 (这部分来自http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/,所以我认为应该可以正常工作)。

然后计算新位置:

new_pos = old_pos + -R.t()*t;

其中 new_pos 和 old_pos 是向量 (3x1),R 是旋转矩阵 (3x3),t 是平移向量 (3x1)。

不幸的是,我没有得到有用的结果,所以也许有人知道可能出了什么问题。

以下是一些结果(以防有人可以确认其中任何一个肯定是错误的):

F = [8.093827077399547e-07, 1.102681999632987e-06, -0.0007939604310854831;
     1.29246107737264e-06, 1.492629957878578e-06, -0.001211264339006535;
     -0.001052930954975217, -0.001278667878010564, 1]

K = [150, 0, 300;
    0, 150, 400;
    0, 0, 1]

E = [0.01821111092414898, 0.02481034499174221, -0.01651092283654529;
     0.02908037424088439, 0.03358417405226801, -0.03397110489649674;
     -0.04396975675562629, -0.05262169424538553, 0.04904210357279387]

t = [0.2970648246214448; 0.7352053067682792; 0.6092828956013705]

R = [0.2048034356172475, 0.4709818957303019, -0.858039396912323;
     -0.8690270040802598, -0.3158728880490416, -0.3808101689488421;
     -0.4503860776474556, 0.8236506374002566, 0.3446041331317597]

【问题讨论】:

  • 您的计算中还有一个错误。 SVD decomp = SVD(E); 可以,但你必须计算一个新的newE = U*diag(1,1,0)*Vt,然后你必须再次得到SVD decomp2 = SVD(newE);
  • 有趣。我从来没有读过这件事。所以我必须用 decomp2 计算 R 和 t 吗?顺便说一句:感谢您的详细回答。我必须检查所有的东西,并会尽快回复。
  • 是的,你必须用 decomp2 计算 R 和 t。这里给出了详细的描述(pp 257-260)robots.ox.ac.uk/~vgg/hzbook/hzbook2/HZepipolar.pdf

标签: opencv rotation translation motion 3d-reconstruction


【解决方案1】:

首先你应该检查是否

x' * F * x = 0

为您的点通信x'x。当然,这应该只适用于使用 RANSAC 进行基本矩阵估计的内点。

此后,您必须像这样将点对应关系转换为标准化图像坐标 (NCC)

xn = inv(K) * x
xn' = inv(K') * x'

其中K' 是第二张图像的固有相机矩阵,x' 是第二张图像的点。我认为在你的情况下是K = K'

使用这些 NCC,您可以像您描述的那样分解您的基本矩阵。您对归一化的相机坐标进行三角测量并检查三角测量点的深度。但要小心,在文献中他们说一点就足以获得正确的旋转和平移。根据我的经验,您应该检查几个点,因为即使在 RANSAC 之后,一个点也可能是异常值。

在分解基本矩阵之前,请确保 E=U*diag(1,1,0)*Vt.对于投影矩阵的四种可能选择,需要此条件才能获得正确的结果。

当您获得正确的旋转和平移后,您可以对所有点对应关系(使用 RANSAC 进行基本矩阵估计的内点)进行三角测量。然后,您应该计算reprojection error。首先,您像这样计算重新投影的位置

xp = K * P * X
xp' = K' * P' * X

其中X 是计算的(同质的)3D 位置。 PP' 是 3x4 投影矩阵。投影矩阵P 通常由恒等式给出。 P' = [R, t] 由前 3 列和前 3 行的旋转矩阵和第四列的平移给出,因此 P 是一个 3x4 矩阵。这仅在您将 3D 位置转换为 homogeneous coordinates 时才有效,即 4x1 向量而不是 3x1。然后,xpxp' 也是齐次坐标,代表您对应点的(重新投影的)2D 位置。

我觉得

new_pos = old_pos + -R.t()*t;

是不正确的,因为首先,您只翻译 old_pos 而您不旋转它,其次,您使用错误的向量进行翻译。上面给出了正确的方法。

因此,在计算重投影点后,您可以计算重投影误差。由于您使用的是齐次坐标,因此您必须对其进行归一化(xp = xp / xp(2),除以最后一个坐标)。这是由

给出的
error = (x(0)-xp(0))^2 + (x(1)-xp(1))^2

如果误差很大,例如 10^2,则您的固有相机校准或旋转/平移不正确(可能两者都有)。根据您的坐标系,您可以尝试反转投影矩阵。因此,您需要先将它们转换为齐次坐标,因为您无法反转 3x4 矩阵(没有伪逆矩阵)。因此,添加第四行 [0 0 0 1],计算逆并删除第四行。

还有一件事是重投影错误。通常,重投影误差是原始点对应(在每个图像中)与重投影位置之间的平方距离。你可以取平方根来得到两个点之间的欧几里得距离。

【讨论】:

  • 等式 x' * F * x = 0 在实践中也正好是 0 吗?像 1,12345*e^-14 这样的值还好吗?我可以在 NCC 计算之前丢弃所有异常值吗?
  • 我尝试了你描述的东西并最终得到了投影矩阵。重投影误差 new_pos = old_pos + -R.t()*t; 完成的。既然你说错了,你知道我怎么用投影矩阵做到这一点吗?
  • 一台摄像机位于(0, 0, 0),另一台位于t。此外,第二个摄像机旋转了R。由Rt组成的矩阵P(称为投影矩阵)是将每个3D点p从单位矩阵表示的坐标系转换为P表示的坐标系的刚体变换.转换由newp = P * p 完成,其中P 是3x4 或4x4 矩阵,p 是齐次3D 点,即4 向量。一般来说,p 的最后一个分量等于 1。
  • 感谢您的回答。你的解释很有帮助,现在看来我得到了有用的结果。
  • 当我分解基本矩阵时,U 和 Vt 只有 0,1 和 -1 个元素,而 S,应该是 diag(1,1,0) 是 diag(4.28,1,0.902 )。由于 U 和 Vt 矩阵已关闭,我无法继续计算平移和旋转。如何正确分解 E 矩阵?
【解决方案2】:

要更新你的相机位置,你必须先更新平移,然后更新旋转矩阵。

t_ref += lambda * (R_ref * t);
R_ref = R * R_ref;

其中 t_ref 和 R_ref 是您的相机状态,R 和 t 是新计算的相机旋转和平移,而 lambda 是比例因子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    相关资源
    最近更新 更多