从基本矩阵(反投影2D到3D)计算3D点

时间:2020-07-16 18:34:52

标签: python math matrix camera vision

我正在尝试从2张图像中计算3D点。但是我不确定我的实现/思想过程是否正确,因为我真的不知道我计算出的3D点/旋转和平移矩阵中哪个是正确的。

我可以提供或完成的事情:

  • 获得了两个摄像机k1k2的固有参数
  • cv2.findFundamentalMat计算基本矩阵(完全确定它是正确的,因为我用等式x' F x = 0对其进行了检查)
k1 = np.array([[512,   0, 512.],
 [  0, 512, 384],
 [  0,   0,   1]]).reshape(3,3)

k2 =np.array([[512,   0, 512.],
 [  0, 512, 384],
 [  0,   0,   1]]).reshape(3,3)

fMatrix = np.array([[ 2.13503670e-06, -1.09093289e-05,  1.34791051e-03],
 [ 1.15140270e-05, -8.93292052e-07, -8.31221024e-03],
 [-4.24200928e-03,  7.99815714e-03,  1.00000000e+00]]).reshape(3,3)

p1 = np.array([752, 573,   1])
p2 = np.array([701, 542,   1])
print(p2.T.dot(fMatrix).dot(p2))
-0.015196065125415714
  • 计算了基本矩阵E = K2.T * F *K1(不确定是否正确)
  • 提取旋转和平移矩阵RR2SbS2b
  • 使用[R | t]构造了4个可能的外部矩阵M1M2M3M4
essentialMatrix = k2.T.dot(fMatrix).dot(k1)
U, S, V = np.linalg.svd(essentialMatrix)

newEssentialMatrix = U.dot(np.diag([1,1,0])).dot(V.T)

U, S, V = np.linalg.svd(newEssentialMatrix)

W = np.array([[0, -1, 0], [1, 0, 0],[0, 0, 1]]).reshape(3,3)
Z = np.array([[0,1,0],[-1,0,0],[0,0,0]]).reshape(3,3)

Sb = U.dot(Z).dot(U.T) # [t]x
R = U.dot(W).dot(V.T) # R
S2b = U.dot(Z.T).dot(U.T) # [t]x
R2 = U.dot(W.T).dot(V.T) # R

t1 = np.array([[Sb[2][1]],[Sb[0][2]],[Sb[1][0]]])
t2 = np.array([[S2b[2][1]],[S2b[0][2]],[S2b[1][0]]])

# M = [U W.T V.T | t] = # M = [U W.T V.T | t] = [R | t]
M1 = np.append(R, t1, axis=1) 
M2 = np.append(R, t2, axis=1)
M3 = np.append(R2, t1, axis=1)
M4 = np.append(R2, t2, axis=1)
  • 尝试验证我需要使用哪个外部/投影矩阵。换句话说,我正在为camera1创建投影矩阵P1 = k1*[I|0]
  • 对于camera2 4个不同的投影矩阵P2 = k2*M1P2 = k2*M2P2 = k2*M3P2 = k2*M4
  • 用\ p1p2cv2.triangulatePoints()的对应点进行测试\计算
    origin = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0]]).reshape(3,4)
    projectionM1 = k1.dot(origin)
    
    projectionM2 = k2.dot(M1)
    p3D = cv2.triangulatePoints(projectionM1,projectionM2,p1[:2],p2[:2])
    print("M1")
    print(p3D/p3D[3])
    print("-----")
    projectionM2 = k2.dot(M2)
    p3D = cv2.triangulatePoints(projectionM1,projectionM2,p1[:2],p2[:2])
    print("M2")
    print(p3D/p3D[3])
    print("-----")
    projectionM2 = k2.dot(M3)
    p3D = cv2.triangulatePoints(projectionM1,projectionM2,p1[:2],p2[:2])
    print("M3")
    print(p3D/p3D[3])
    print("-----")
    projectionM2 = k2.dot(M4)
    p3D = cv2.triangulatePoints(projectionM1,projectionM2,p1[:2],p2[:2])
    print("M4")
    print(p3D/p3D[3])

这是我的结果:

    M1
    [[-0.19115383]
     [-0.12595232]
     [-0.51133412]
     [ 1.        ]]
    -----
    M2
    [[0.19115383]
     [0.12595232]
     [0.51133412]
     [1.        ]]
    -----
    M3
    [[-0.6098932 ]
     [-0.25755958]
     [-1.29386456]
     [ 1.        ]]
    -----
    M4
    [[0.6098932 ]
     [0.25755958]
     [1.29386456]
     [1.        ]]

所以我的问题是哪一个是正确的? 我的猜测是M2或M4,因为它们仅包含正Z值,但是再说一次,我也不知道camera1的坐标系是如何定义的,也许M1或M3可能是正确的。 在this picture中,您可以看到camera1的透视图以及应该计算的点。

如果还有其他遗漏或错误的请不要犹豫告诉我。非常感谢您的帮助。

0 个答案:

没有答案