8

我有两个来自相机的连续图像,我想估计相机姿势的变化: 两张带相机运动的照片

我计算光流:

Const MAXFEATURES As Integer = 100
imgA = New Image(Of [Structure].Bgr, Byte)("pic1.bmp")
imgB = New Image(Of [Structure].Bgr, Byte)("pic2.bmp")
grayA = imgA.Convert(Of Gray, Byte)()
grayB = imgB.Convert(Of Gray, Byte)()
imagesize = cvGetSize(grayA)
pyrBufferA = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) _
    (imagesize.Width + 8, imagesize.Height / 3)
pyrBufferB = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) _
    (imagesize.Width + 8, imagesize.Height / 3)
features = MAXFEATURES
featuresA = grayA.GoodFeaturesToTrack(features, 0.01, 25, 3)
grayA.FindCornerSubPix(featuresA, New System.Drawing.Size(10, 10),
                       New System.Drawing.Size(-1, -1),
                       New Emgu.CV.Structure.MCvTermCriteria(20, 0.03))
features = featuresA(0).Length
Emgu.CV.OpticalFlow.PyrLK(grayA, grayB, pyrBufferA, pyrBufferB, _
                          featuresA(0), New Size(25, 25), 3, _
                          New Emgu.CV.Structure.MCvTermCriteria(20, 0.03D),
                          flags, featuresB(0), status, errors)
pointsA = New Matrix(Of Single)(features, 2)
pointsB = New Matrix(Of Single)(features, 2)
For i As Integer = 0 To features - 1
    pointsA(i, 0) = featuresA(0)(i).X
    pointsA(i, 1) = featuresA(0)(i).Y
    pointsB(i, 0) = featuresB(0)(i).X
    pointsB(i, 1) = featuresB(0)(i).Y
Next
Dim Homography As New Matrix(Of Double)(3, 3)
cvFindHomography(pointsA.Ptr, pointsB.Ptr, Homography, HOMOGRAPHY_METHOD.RANSAC, 1, 0)

它看起来是正确的,相机向左和向上移动: 光流 现在我想知道相机移动和旋转了多少。如果我声明我的相机位置和它在看什么:

' Create camera location at origin and lookat (straight ahead, 1 in the Z axis)
Location = New Matrix(Of Double)(2, 3)
location(0, 0) = 0 ' X location
location(0, 1) = 0 ' Y location
location(0, 2) = 0 ' Z location
location(1, 0) = 0 ' X lookat
location(1, 1) = 0 ' Y lookat
location(1, 2) = 1 ' Z lookat

如何计算新位置和外观?

如果我做这一切都错了,或者如果有更好的方法,任何建议都将非常受欢迎,谢谢!

4

2 回答 2

8

对于纯相机旋转 R = A -1 HA。为了证明这一点,考虑图像到平面的单应性 H1=A 和 H2=AR,其中 A 是相机固有矩阵。那么H12=H2*H1 -1 =A -1 RA,由此可以得到R

相机翻译更难估计。如果相机翻译你必须先找到一个基本矩阵(不是单应性): x T Fx=0 然后将其转换为基本矩阵 E=A T FA; 然后可以将 E 分解为旋转和平移 E=t x R,其中 t x表示向量积矩阵。分解不明显,看这个

您获得的旋转将是精确的,而平移矢量只能按比例找到。直观地说,这种缩放意味着仅从两张图像中,您无法真正说出物体是近而小还是远而大。为了消除歧义,我们可以使用熟悉大小的对象、已知两点之间的距离等。

最后请注意,人类视觉系统也有类似的问题:虽然我们“知道”我们眼睛之间的距离,但当它们汇聚在物体上时,视差始终为零,仅从视差我们无法说出距离是多少。人类视觉依靠来自眼睛版本信号的三角测量来计算绝对距离。

于 2014-03-12T00:15:56.750 回答
5

好吧,您所看到的简单来说就是勾股定理问题a^2 + b^2 = c^2。然而,当涉及到基于相机的应用程序时,事情并不是很容易准确确定。您已经找到了“a”所需的一半细节,但是找到“b”或“c”要困难得多。

简短的回答

基本上它不能用一个相机来完成。但它可以用两个相机完成。

冗长的答案 (我想我会更深入地解释,没有双关语的意思)

我会尝试解释一下,假设我们在图像中选择两个点并将相机向左移动。我们知道每个点 B1 到相机的距离是 20mm ,点 B2 是 40mm 。现在假设我们处理图像并且我们的测量是 A1 是 (0,2) 和 A2 是 (0,4) 这些分别与 B1 和 B2 有关。现在 A1 和 A2 不是测量值;它们是运动的像素。

我们现在要做的是将 A1 和 A2 的变化乘以一个计算出的常数,该常数将是 B1 和 B2 处的真实世界距离。注意:根据测量 B*,每一个都是不同的。这一切都与视角有关,或者在不同距离的摄影中更常见地称为视野。如果您知道相机 CCD 上每个像素的大小以及相机内部镜头的 f 值,您就可以准确地计算出常数。

我希望情况并非如此,因此在不同的距离处,您必须放置一个您知道长度的对象并查看它占用了多少像素。关闭您可以使用尺子使事情变得更容易。通过这些测量。您获取这些数据并形成一条具有最佳拟合线的曲线。其中 X 轴将是对象的距离,Y 轴将是像素与距离比的常数,您必须将其乘以移动。

那么我们如何应用这条曲线。好吧,这是猜测工作。理论上,运动 A* 的测量值越大,物体离相机越近。在我们的示例中,A1 > A2 的比率分别为 5 毫米和 3 毫米,我们现在知道点 B1 移动了 10 毫米(2x5 毫米),而 B2 移动了 6 毫米(2x6 毫米)。但是让我们面对现实吧——我们永远不会知道 B,我们也永远无法判断移动的距离是 20 像素的物体靠近不移动很远还是远处的物体移动了很远的距离。这就是为什么像 Xbox Kinect 这样的东西使用额外的传感器来获取可以与图像中的对象相关联的深度信息。

您可以尝试使用两个摄像头来尝试,因为这些摄像头之间的距离是已知的,可以更准确地计算运动(有效地不使用深度传感器)。这背后的数学非常复杂,我建议查找一些关于该主题的期刊论文。如果你想让我解释这个理论,我可以尝试。

我所有的经验都来自为我的 PHD 设计高速视频采集和图像处理,所以相信我,这不能用一台相机完成,抱歉。我希望这会有所帮助。

干杯

克里斯

[编辑]

我打算添加一条评论,但由于信息量很大,这更容易:

因为它是 Kinect,所以我假设你有一些与每个点相关的相关深度信息,如果没有,你需要弄清楚如何获得它。

您需要开始的等式是视野 ( FOV ):

o/d = i/f

在哪里:

f等于通常以 mm 为单位给出的镜头焦距(即 18 28 30 50 是标准示例)

d是从 kinect 数据中收集到的距镜头的物距

o是物体尺寸(或垂直于光轴并被光轴二等分的“视野”)。

i是图像尺寸(或垂直于光轴并被光轴二等分的“视场光阑”)。

我们需要计算i,其中o是我们的未知数,因此对于i(这是对角线测量),

我们将需要 ccd 上像素的大小,单位为微米或微米,您需要找到此信息,因为我们将其视为 14 微米,这是中档面阵相机的标准。

所以首先我们需要计算出 i 水平维度(ih),它是相机宽度的像素数乘以 ccd 像素的大小(我们将使用 640 x 320)

所以:ih = 640*14um = 8960um

   = 8960/1000 = 8.96mm

现在我们需要i垂直维度 ( iv ) 相同的过程,但高度

所以:iv = (320 * 14um) / 1000 = 4.48mm

现在i由勾股定理 勾股定理 a^2 + b^2 = c^2

所以:i = sqrt(ih^2 _ iv^2)

  = 10.02 mm

现在我们假设我们有一个 28 毫米镜头。同样,必须找出这个确切的值。所以我们的方程重新排列给我们o是:

o = (i * d) / f

记住o是对角线(我们假设物体或点距离 50 毫米):

o = (10.02mm * 50mm) / 28mm

17.89mm

现在我们需要计算出 o 水平尺寸 ( oh ) 和 o 垂直尺寸 ( ov ),因为这将为我们提供对象移动的每个像素的距离。现在,由于FOV α CCDi与o成正比,我们将计算出比率k

k = i/o

= 10.02 / 17.89 

= 0.56

所以:

o水平尺寸():

= ih / k

= 8.96 毫米 / 0.56 = 16 毫米/像素

o垂直尺寸 ( ov ):

ov = iv / k

= 4.48 毫米 / 0.56 = 8 毫米/像素

现在我们有了我们需要的常量,让我们在一个例子中使用它。如果我们在 50mm 处的物体从位置 (0,0) 移动到 (2,4),那么现实生活中的测量结果是:

(2*16mm , 4*8mm) = (32mm,32mm)

同样,勾股定理:a^2 + b^2 = c^2

总距离 = sqrt(32^2 + 32^2)

           = 45.25mm

我知道这很复杂,但是一旦您在程序中使用了它,它就会变得更容易。因此,对于每个点,您都必须重复至少一半的过程,因为d会改变因此o对于您检查的每个点。

希望这能让你上路,

干杯克里斯

于 2011-09-12T18:57:00.807 回答