就像问题说的那样,我正在寻找一个完整的、最小的、来自运动(又名 3d 重建)管道的结构的工作示例。
马上让我说我没有相机参数。我不知道焦距或相机内在特性。所以马上,90% 的示例/教程 都是 无效的。
关于这个主题有很多问题,但代码只是片段,而不是完整的 SfM 过程。许多指令相互矛盾,或者只是猜测,开源外部库很难遵循。
所以我正在寻找一个简短、完整、最小的工作示例。最重要的是工作要求,因为那里有这么多代码会产生不好的结果。
我用下面的代码做了一个尝试。我使用匹配对的合成数据,因此没有噪音或不良对应问题需要解决。目标是从 2 个视图重建一个立方体(8 个 3d 点),每个视图有 8 个 2d 点。然而,最终的结果很糟糕。没有立方体形状的外观。(我已经尝试对数据进行规范化和居中,这不是问题)。
任何可以提供更好的最小工作示例或指出我的尝试有什么问题的人都将受到赞赏。
import cv2
import numpy as np
import scipy.linalg
def combineTR(T,R): #turn a translation vector and a rotation matrix into one 3x4 projection matrix
T4 = np.eye(4)
T4[:3, 3] = T # make it 4x4 so we can dot product it
R4 = np.eye(4)
R4[:3, :3] = R
P = np.dot(T4, R4) # combine rotation and translation into one matrix
P = P[:3, :] # cut off bottom row
return P
####################################################################
# # ground truth
# Wpts = np.array([[1, 1, 1], # A Cube in world points
# [1, 2, 1],
# [2, 1, 1],
# [2, 2, 1],
# [1, 1, 2],
# [1, 2, 2],
# [2, 1, 2],
# [2, 2, 2]])
views = np.array(
[[[ 0.211, 0.392],
[ 0.179, 0.429],
[ 0.421, 0.392],
[ 0.358, 0.429],
[ 0.189, 0.193],
[ 0.163, 0.254],
[ 0.378, 0.193],
[ 0.326, 0.254]],
[[ 0.392, 0.211],
[ 0.392, 0.421],
[ 0.429, 0.179],
[ 0.429, 0.358],
[ 0.193, 0.189],
[ 0.193, 0.378],
[ 0.254, 0.163],
[ 0.254, 0.326]]])
F = cv2.findFundamentalMat(views[0], views[1],cv2.FM_8POINT)[0]
# hartley and zimmermans method for finding P
e2 = scipy.linalg.null_space(F.T) #epipole of second image
C2R = np.cross(e2.T, F) #camera 2 rotation
C2T = e2.T[0]
P = combineTR(C2T, C2R) #projection matrix for camera 2
R = np.eye(3) # rotation matrix for camera 1
T = [0, 0, 0] # translation
P0 = combineTR(T,R)
tpts = cv2.triangulatePoints(P0,P,views[0].T,views[1].T) #triangulated point
tpts /= tpts[-1] #divide by last row and scale it
tpts *= -100
print(tpts)