计算多个图像中关键点的3D坐标

时间:2016-07-12 08:34:35

标签: opencv computer-vision stereo-3d 3d-reconstruction

我有同一校准相机拍摄的物体的多个图像。让我们说校准意味着内在和外在参数(我可以在对象旁边放置一个棋盘,因此可以检索所有参数)。在这些图像上,我可以使用SIFT或SURF找到匹配的关键点,以及一些匹配算法,这是基本的OpenCV。但是如何从多个图像中对这些点进行三维重建呢?这不是经典的立体声排列,因此有超过2个图像具有相同的对象点,我希望尽可能多地使用它们以提高准确度。

是否有内置的OpenCV功能可以执行此操作?

(请注意,这是离线完成的,解决方案不需要快速但强大)

2 个答案:

答案 0 :(得分:1)

我猜你正在寻找所谓的Structur from motion方法。他们使用来自不同视点的多个图像并返回3D重建(例如,点云)。看起来OpenCV在contrib包中有一个SfM模块,但我没有经验。

但是,我曾经与bundler合作。它非常简单,并将整个信息(摄像机校准和点位置)作为文本文件返回,您可以使用Meshlab查看点云。请注意,它使用SIFT关键点和描述符来建立通信。

答案 1 :(得分:1)

我想我找到了解决方案。运动算法的结构处理相机未校准的情况,但在这种情况下,所有内在和外在参数都是已知的。

问题会降级为线性最小二乘问题:

我们必须计算单个对象点的坐标:

X = [x, y, z, 1]'
C = [x, y, z]'
X = [[C], [1]]

我们得到 n 图像,它们具有这些转换矩阵:

Pi = Ki * [Ri|ti]

这些矩阵已知。对象点投影在

上的图像上
U = [ui, vi] 

我们可以用齐次坐标编写(运算符*代表矩阵乘法,点积和标量乘法):

[ui * wi, vi * wi, wi]' = Pi * X

Pi = [[p11i, p12i, p13i, p14i],
      [p21i, p22i, p23i, p24i],
      [p31i, p32i, p33i, p34i]]

让我们定义以下内容:

p1i = [p11i, p12i, p13i] (the first row of Pi missing the last element)
p2i = [p21i, p22i, p23i] (the second row of Pi missing the last element)
p3i = [p31i, p32i, p33i] (the third row of Pi missing the last element)

a1i = p14i
a2i = p24i
a3i = p34i

然后我们可以写:

Q = [x, y, z]
wi = p3i * Q + a3i
ui = (p1i * Q + a1i) / wi = 
   = (p1i * Q + a1i) / (p3i * Q + a3i)
ui * p3i * Q + ui * a3i - p1i * Q - a1i = 0
(ui * p3i - p1i) * Q = a1i - a3i

同样适用于 vi

(vi * p3i - p2i) * Q = a2i - a3i

这适用于 i = 1..n 。我们可以用矩阵形式写出来:

G * Q = b

G = [[u1 * p31 - p11],
     [v1 * p31 - p21],
     [u2 * p32 - p12],
     [v2 * p32 - p22],
     ...         
     [un * p3n - p1n],
     [vn * p3n - p2n]]

b = [[a11 - a31 * u1],
     [a21 - a31 * v1],
     [a12 - a32 * u2],
     [a22 - a32 * v2],
     ...
     [a1n - a3n * un],
     [a2n - a3n * vn]]

由于 G b Pi 矩阵中已知,并且图像指向 [ui,vi] ,我们可以计算 G 的伪逆(称之为 G _ ),并计算:

Q = G_ * b