从单应性中提取变换和旋转矩阵?

smi*_*man 8 vb.net opencv matrix homography emgucv

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

我计算光流量:

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)
Run Code Online (Sandbox Code Playgroud)

它看起来正确,相机向左和向上移动: 光流 现在我想知道相机移动和旋转了多少.如果我宣布我的相机位置及其所看到的内容:

' 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
Run Code Online (Sandbox Code Playgroud)

如何计算新位置和外观?

如果我做错了,或者有更好的方法,那么任何建议都会非常受欢迎,谢谢!

Vla*_*lad 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表示矢量积矩阵.分解不明显,看这个.

您获得的旋转将是精确的,而翻译矢量只能按比例找到.直观地说,这种缩放意味着仅从两个图像中就无法确定对象是近距离还是小距离还是远距离大.为了消除歧义,我们可以使用熟悉的尺寸对象,两点之间的已知距离等.

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


Chr*_*ris 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的比率分别为5mm和3mm,我们现在知道B1点移动了10mm(2x5mm),B2移动了6mm(2x6mm).但是让我们面对它 - 我们永远不会知道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上像素的大小,这将以微米或μm为单位,您将需要找到这些信息,因为我们知道我们将其视为14um,这是中端区域扫描相机的标准.

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

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

   = 8960/1000 = 8.96mm
Run Code Online (Sandbox Code Playgroud)

现在,我们需要的垂直尺寸(IV)相同的过程,但高度

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

现在发现毕达哥拉斯定理毕达哥拉斯定理a ^ 2 + b ^ 2 = c ^ 2

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

  = 10.02 mm
Run Code Online (Sandbox Code Playgroud)

现在我们假设我们有28毫米镜头.同样,必须找到这个确切的值.因此,我们的公式是重排给我们Ø是:

o =(i*d)/ f

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

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

17.89mm
Run Code Online (Sandbox Code Playgroud)

现在我们需要计算水平尺寸()和垂直尺寸(ov),因为这将给出物体移动的每个像素的距离.现在,当FOVαCCDio成正比时,我们将计算出比率k

k = i/o

= 10.02 / 17.89 

= 0.56
Run Code Online (Sandbox Code Playgroud)

所以:

o水平尺寸():

= ih/k

= 8.96mm/0.56 = 每像素16mm

o垂直尺寸(ov):

ov = iv/k

= 4.48mm/0.56 = 每像素8mm

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

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

再次,毕达哥拉斯定理:a ^ 2 + b ^ 2 = c ^ 2

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

           = 45.25mm
Run Code Online (Sandbox Code Playgroud)

复杂我知道,但是一旦你在一个程序中有这个,它就会更容易.因此,对于每个点,您将不得不重复至少一半的过程,因为d将改变,因此o对于您的检查的每个点.

希望这能让你顺利上路,

干杯克里斯