从单应性中提取变换和旋转矩阵?
Posted
技术标签:
【中文标题】从单应性中提取变换和旋转矩阵?【英文标题】:Extract transform and rotation matrices from homography? 【发布时间】:2011-11-15 09:02:42 【问题描述】:我有 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)
它看起来是正确的,相机向左和向上移动: 现在我想知道相机移动和旋转了多少。如果我声明我的相机位置和它在看什么:
' 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
我如何计算新的位置和lookat?
如果我做错了,或者如果有更好的方法,任何建议都会非常受欢迎,谢谢!
【问题讨论】:
我悬赏 500 来回答这个问题 ***.com/questions/7414809/… 【参考方案1】:对于纯相机旋转 R = A-1HA。为了证明这一点,考虑图像到平面的单应性 H1=A 和 H2=AR,其中 A 是相机固有矩阵。那么H12=H2*H1-1=A-1RA,从中可以得到R
相机翻译更难估计。如果相机翻译你必须先找到一个基本矩阵(不是单应性):xTFx=0 然后将它转换成一个基本矩阵 E=ATFA;然后可以将 E 分解为旋转和平移 E=txR,其中 tx 表示向量积矩阵。分解不明显,见this。
您获得的旋转将是精确的,而平移矢量只能按比例找到。直观地说,这种缩放意味着仅从两张图像中,您无法真正说出物体是近而小还是远而大。为了消除歧义,我们可以使用熟悉大小的对象、已知两点之间的距离等。
最后请注意,人类的视觉系统也有类似的问题:尽管我们“知道”我们眼睛之间的距离,但当它们汇聚到物体上时,视差始终为零,仅凭视差我们无法说出距离是多少。人类视觉依赖于眼睛版本信号的三角测量来计算绝对距离。
【讨论】:
这是一个非常简洁的答案,谢谢!它应该得到更多的 +1。 h12 是单应性或 1 wrt 2 或其他,即 p1= h12*p2 或 p2 = h12*p1 @Vlad 请问up to scale的真正含义是什么?这是否意味着规模被认为是一个?【参考方案2】:嗯,简单来说,您看到的是 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 的比率分别为 5 毫米和 3 毫米,我们现在知道点 B1 移动了 10 毫米(2x5 毫米),而 B2 移动了 6 毫米(2x6 毫米)。但是让我们面对现实吧——我们永远不会知道 B,我们永远也无法判断移动的距离是 20 像素的物体靠近不移动很远还是远处的物体移动了很远的距离。这就是为什么像 Xbox Kinect 这样的东西使用额外的传感器来获取可以与图像中的对象相关联的深度信息。
您可以尝试使用两个摄像头进行尝试,因为这些摄像头之间的距离是已知的,因此可以更准确地计算运动(有效地不使用深度传感器)。这背后的数学非常复杂,我建议查找一些关于该主题的期刊论文。如果你想让我解释这个理论,我可以尝试。
我的所有经验都来自为我的 PHD 设计高速视频采集和图像处理,所以请相信我,这不能用一台相机完成,抱歉。我希望这会有所帮助。
干杯
克里斯
[编辑]
我打算添加评论,但由于信息量大,这更容易:
因为它是 Kinect,所以我假设您有一些与每个点相关的深度信息,否则您需要弄清楚如何获得它。
你需要开始的方程式是视野(FOV):
o/d = i/f
地点:
f 等于镜头的焦距,通常以毫米为单位(即 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 α CCD 或 i 与 o 成正比,我们将计算出一个比率 k
k = i/o
= 10.02 / 17.89
= 0.56
所以:
o 水平尺寸(oh):
哦 = 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
我知道这很复杂,但是一旦您在程序中使用它,它就会变得更容易。因此,对于每个点,您都必须重复至少一半的过程,因为 d 会在您检查的每个点上发生变化,因此 o。
希望这能让您顺利上路,
干杯 克里斯
【讨论】:
感谢您抽出宝贵的时间和详细的回复。我确实有相机内在函数,因此(我认为)我的问题与拥有 2 个相机相同。我的理解是单应性表示camera2相对于camera1的位置,由特征之间红线的不同长度表示。假设良好的特征(并且暂时忽略被遮挡的几何图形),那组线只能由给定的运动产生。从 OpenCV 书第 191 页上的相机校准来看,这似乎是可行的,但我的 trig 太差了。你猜对了,它是 Kinect>;-) 嗨,我已经为您提供了答案中所需的计算,它确实需要来自 Kinect 的深度信息。我希望 CCD 和像素大小可以在网络上的其他地方获得。希望对你有帮助 感谢 Chris,这让事情变得更加清晰(为什么其他人总是把事情搞得这么复杂?)。我从图像开始,希望使用光流来帮助我“定位”深度数据,显然我无法从图像中得出真实世界的距离,如您所示。现在我有了深度数据,转化为现实世界(以毫米为单位的点云 [X,Y,Z])。我仍然在找到翻译+旋转之后,我知道我需要的是捆绑调整。有什么想法可以在 .NET 中找到示例(C# 或 VB,C 不是自然而然的)?再次感谢:) 我真的需要一个解决方案。我已经悬赏了这个问题的答案***.com/questions/4520865/… 您好,我会调查一下,如果我找到答案,我会通知您,但我不确定能否帮助您,非常抱歉,请保重以上是关于从单应性中提取变换和旋转矩阵?的主要内容,如果未能解决你的问题,请参考以下文章