2011-09-12 162 views
8

我有一个摄像头2倍连续的图像,我想估计摄像头的改变姿势: two pictures with camera movement从单应矩阵提取变换和旋转矩阵?

我计算光流:

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) 

,它看起来正确,相机向左移动和向上: optical flow 现在我想知道相机移动和旋转了多少。如果我声明我的相机位置和它正在查看的内容:

' 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 

如何计算新的位置和外观?

如果我这样做是错误的或者如果有更好的方法,任何建议将非常欢迎,谢谢!

+0

我为这个问题的答案提供500的赏金http://stackoverflow.com/questions/7414809/extract-projective-homography-from-two-kinect-depth-maps – smirkingman

回答

5

那么你看什么是简单的条件a Pythagorean theorem problem 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 *,每一个都是不同的。这一切都与Angle of view有关,或者在不同距离的摄影中更一般地称为视野。如果您知道摄像机CCD上每个像素的大小以及摄像机内镜头的f值,则可以精确计算常量。

我认为情况并非如此,所以在不同的距离处,您必须放置一个您知道长度的对象并查看它占用了多少像素。关闭你可以使用一把尺子使事情变得更简单。通过这些测量。您可以获取这些数据并形成一条最适合的曲线。 X轴将是物体的距离,Y轴将是像素与距离比的常数,您必须乘以运动。

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

在尝试什么能具有两个相机进行尝试,因为这些摄像机之间的距离是已知的,可以更准确地计算出的移动(实际上不使用深度传感器)。这背后的数学非常复杂,我建议找了一些关于这个问题期刊论文。如果你想让我解释这个理论,我可以尝试。

我所有的经验来自于设计高速视频采集和图像处理我的博士如此信任我,它不能与一台摄像机来完成,对不起。我希望这有助于一些。

干杯

克里斯

[编辑]

我要添加评论,但这种情况很容易由于大部分信息:

既然是Kinect的我会假设你有每个点相关联如果不是你将需要弄清楚如何得到这个一些相关的深度信息。

,你需要开始用该公式对于视场(FOV):

O/d = I/F

其中:

˚F等于透镜的焦距通常以毫米为单位(即18 28 30 50是标准示例)

d是从透镜的物体距离从超高动力学数据收集

Ô是物体尺寸(或“视野”垂直于通过所述光轴平分)。

i是图像尺寸(或“场截止”,垂直于光轴且被光轴平分)。

我们需要计算,其中Ø是我们不明所以的(这是一个对角线测量),

我们需要在CCD这将在像素的大小微米或微米,你需要寻找这些信息了,为了知道我们会把它作为14um这是一款中端区域扫描相机的标准。

所以首先我们需要计算出我水平尺寸(IH),其是照相机乘以由CCD像素的尺寸的宽度的像素的数量(我们将使用640×320)

这样:IH = 640 * 14um = 8960um

= 8960/1000 = 8.96mm 

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

这样:IV =(320 * 14um)/ 1000 = 4.48毫米

现在通过勾股定理勾股定理一个发现^ 2 + B^2 = C^2

这样: = SQRT(IH^2 _ IV^2)

= 10.02 mm 

现在我们将假设我们有一个28毫米的镜头。再次,这个确切的价值将不得不被发现。因此,我们的公式重新安排给我们Ø是:

O =(I * d)/ F

记住Ø将是对角线(我们假设对象或点为50mm远):

Ô =(10.02毫米* 50mm)的/28毫米

17.89mm 

现在,我们需要计算出水平尺寸(,)和垂直尺寸(ov),因为这会给我们物体移动的每个像素的距离。现在,作为FOVαCCD成正比ö我们将制定出一个比ķ

ķ = I/O

= 10.02/17.89 

= 0.56 

这样:

o横向尺寸( ):

= IH/K

=8.96毫米/ 0。每像素56 = 16毫米

ö垂直尺寸(OV):

OV = IV/K

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

现在我们有我们需要的常量,让我们在一个例子中使用它。如果我们在从位置(0,0)50毫米移动到(2,4)然后在现实生活中的测量对象:

(2 * 16毫米4 * 8毫米)=(32毫米,32毫米)

再次,一个勾股定理:A^2 + b^2 = C^2

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

  = 45.25mm 

并发我知道,但一旦有这在一个程序中它更容易。因此,对于每一个点,你将不得不重复至少有一半的过程d上因此Ø将改变你的检查每一个点。

希望这可以让你对你的方式,

干杯 克里斯

+0

感谢您花时间和详细的答复。我确实有相机内在因素,因此(我认为)我的问题与拥有2个相机相同。我的理解是,单应性表示相机2将相对于相机1的位置,用特征之间红线的不同长度表示。假设有良好的特征(并且忽略当前遮挡的几何图形),该组线条只能由给定的运动产生。从OpenCV书籍第191页的摄像机校准看来,它似乎是可行的,但我的触发器太差了。你正确地猜到了,这是一个Kinect >-) – smirkingman

+0

嗨,我已经提供了你需要的计算结果,它需要来自Kinect的深度信息。我希望CCD和像素大小可以在网络上使用。希望它有帮助 – Chris

+0

感谢Chris,这让事情变得更加清晰(为什么其他人总是让它变得如此复杂?)。我从图像开始,希望能够使用光流来帮助“定位”深度数据,显然,我无法从图像中推导出真实世界的距离。现在我已经将深度数据转化为现实世界(以毫米为单位的点云[X,Y,Z])。我仍然在找到翻译+旋转之后,并且我明白我需要的是捆绑调整。任何想法,我可以在.NET中找到一个例子(C#或VB,C不是东西)?再次感谢:) – smirkingman

8

对于纯相机旋转R = A -1 HA。为了证明这个考虑图像平面单应H1 = A和H2 = AR,其中A是相机固有矩阵。然后H12 = H2 * H1 -1 = A -1 RA,从中可以获得R个

相机翻译更难估计。如果相机转换,你必须找到一个基本矩阵第一(不单应):X 牛逼 Fx的= 0,然后将其转换成一个基本矩阵E = A 牛逼 FA;然后,你可以分解成Ë旋转和平移E =吨 X R,其中t X指向量积矩阵。分解不明显,见this

,你得到的将是准确的,而平移矢量可以发现最多只能缩放旋转。直观地说,这种缩放意味着仅从两幅图像中就无法确定物体是近距离的还是小的距离,还是很远。为了消除歧义,我们可以使用熟悉的尺寸物体,两点之间的已知距离等。

最后要注意的是,人类视觉系统有一个类似的问题:尽管我们“知道”我们眼睛之间的距离,当它们收敛时对象的差距总是为零,单从差距来看,我们不能说距离是多少。人类视觉依赖于来自眼睛版本信号的三角测量来找出绝对距离。

+0

这是一个非常好的和简洁的答案,谢谢!它值得更多+1。 – jhegedus

+0

h12是单应性或1重或2,否则即p1 = h12 * p2或p2 = h12 * p1 @ Vlad –