《Learning OpenCV3》ch19:双目标定与立体匹配
上一章讲到一些射影几何和单摄像机参数标定的内容,主要还是为了这一章的内容来服务。我们会用到18章的一些概念,比如说内参数矩阵M,畸变参数,旋转矩阵等内容。
目前来说,还没有可靠的方法能够在单幅图像的情况下进行标定和提取三维信息。在立体视觉中,通过把从不同摄像机同时获取的两个或更多的图像的特征,与其他图像中的相关特征进行匹配,分析视差,产生深度信息。
双目摄像头标定
立体成像
使用双目摄像机进行立体成像包括四个步骤:
-
使用数学的方法消除透镜畸变,上一章已经提到。
-
调整摄像机之间的位置和距离,并根据标定图像来进行计算。这一步称为“标定”。
-
在两个摄像头得到的图像中寻找相同的特征,得到视差d,这一步称为“匹配”。
-
通过三角测量的方法将视差图转化为深度图,这一步称为“重投影”。
我们从最后一步开始,然后分析前三个步骤。
三角测量
想象一个理想的立体装置,图像没有畸变,图像平面共面,光轴平行,焦距相同,主点已经被校准到该有的位置(没有接触过这些概念的可以看我的另一篇读书笔记)。
此外,假设摄像机前向平行排列,即每一个像素行和另一个摄像机中的像素行精确地对齐,并能够在物理世界中找到一点P,在左右图像中分别有成像点。那么,通过相似三角形可以得到深度Z。
理想设备相似三角形
Obviously,由公式可知,视差与深度成反比,并且存在非线性关系。也就是说,当视差趋近于零时,微小的变化不会对深度有太大的影响,反之亦然。可以得出结论,立体视觉系统只有在屋里与摄像机距离比较近时才有比较高的深度分辨率。
深度与视差成反比用于立体视觉中OpenCV的二维和三维坐标系如下。
坐标系如上
了解简化模型之后,就要讨论丑陋的现实模型了。现实世界中摄像机不会严格地前向平行对准,虽然可以通过数学的方法矫正图像,但还是要尽量对准,这样使数学变换更容易处理。
并且为了得到更好的结果,需要同步摄像机,即在同一时刻捕获图像,那么物体如果移动,就会出现问题。我们的目标是从数学上将两个摄像机对准到一个观察平面,使得摄像机之间的像素行使彼此精确对准的。
真实情况
对极几何
之前搞全景图像拼接的时候用到过,可以看看这篇文章。图中的连接投影中心的直线与投影平面(projective plane)的交点称为极点(epipole),连接投影点和极点的虚线称为极线(epipolar line)。两条极线显然是共面的,称为极面。
根据推导和几何领域的公理,我们得出以下结论:
-
摄像机视图中的每一个三维点(图中的点P)都被包含在与每个图像相交的极面中。两者产生的直线是极线。
-
给定一幅图像上的特征点,在另一个图像中相匹配的点一定位于对应的极线上,这被称为“极线约束”。
-
极线约束意味着,一旦我们知道了立体实验设备之间的对极几何,在两幅图像之间匹配特征的二维搜索可以转变为沿着极线的一维搜索(在应用三角测量原理的时候)。这不仅会极大地节省计算成本,同时会帮助我们排除许多可能会产生虚假匹配的点。
本征矩阵和基本矩阵
本征矩阵E包含关于物理空间中两个摄像机的平移和旋转的信息。基本矩阵(基础矩阵)F除了包含相同的信息外,矩阵F还包含两个摄像机的内参数,他可以在像素坐标系上将两台摄像机关联。
平移和旋转接下来就要讨论一下公式推导的问题了。
具体的思路是用我们已知的极面来把所有这些关联起来。设法向量n,x为极面上的任意一点,a为极面上的固定点,则有
法向量垂直于相应平面
可以用叉乘的方式构造法向量,如下
叉乘得到一个垂直的向量我们可以将已经知道的等式变换一下
回想一下上面的图 简单变换
上一章讲到,旋转矩阵为对称阵,则有
对称矩阵跟据上述条件,则得到
带入上上上上式
根据线代知识,我们可以讲叉乘写成一个矩阵乘法的形式
叉乘转换成矩阵乘法
印象中线代老师好像没讲这个。可以看看这篇博客,其实推导挺简单的
将这个条件回代,得到一个重要结论
重要结论点乘R·S就是我们对本征矩阵E的定义
最终结论
实际使用中,我们需要的是投影平面上的观察到的点。我们可以利用投影公式
回忆一下相机模型
则最终结论的左边可以变成
实际使用
看似我们可以通过基础矩阵来将左边的成像点映射到另一边,但很遗憾的是,E是一个秩亏矩阵(一个秩为2的3x3矩阵),所以只能将一个点映射到一条直线上。
矩阵E包含两个摄像机相关的所有几何信息,但不包括相机的内部参数。上面推导中的向量p只是几何意义上的点,通过下式跟像素点关联起来
M为内参矩阵则根据前面的推导结论,可以得到
有点丑那么中间的一坨就是基本矩阵的定义
基本矩阵
实际使用中就可以这样用
基本矩阵的最终推导
简而言之,基本矩阵F和本征矩阵E差别在于,基础矩阵在图像像素坐标中操作,本征矩阵E在物理坐标系中操作。相类似的,矩阵F的秩也为2
对于OpenCV中这两个玩意怎么计算,还是看我之前写的这篇文章。
立体标定(Stereo Calibration)
讲到这里,就该使用棋盘进行立体标定了。
书的中文版中将 Stereo Calibration 翻译成立体校正,这个很奇怪,按道理说应该是立体标定。后面讲到 Stereo Rectification 的时候又翻译成立体校正,估计前面是错的,后面才是正确的。
具体实现跟单目标定差不多。除了计算出矩阵E和F,还需要计算出两个摄像机之间的旋转矩阵R和平移向量T。方法是分别计算出两个摄像机的R和T,再由以下公式计算
旋转
平移
立体矫正(Stereo Rectification)
正如之前说到,不存在理想的前线平行对准。那么立体矫正的目的就在于:将两个摄像机的像平面重新映射,使两者位于完全相同的平面上,图像行完全对准到前向平行对准。
经过标定和矫正,我们希望两个摄像机之间的图像行是对准的,以使立体对应(在两个不同摄像机视图中找到同一个点可靠和计算容易。
OpenCV中实现了两个立体矫正算法:1)Hartley算法,只使用基本矩阵产生非标定立体视觉;2)Bouguet算法,使用两个标定摄像机中的旋转和平移参数。一般使用Bouguet算法,这里只讨论这个。算法的主要思想如下:
-
计算出来的旋转矩阵R切成两半,左图像旋转一半,右图像旋转一半,这样重投影畸变会比较小。
-
为了使极线平行对准,我们需要将极点变换到无穷远并使极线平行对准的矩阵Rrect。
把旋转矩阵砍一半
把旋转矩阵砍一半
设一个可以将极点变换到无穷远的矩阵如下
校正矩阵
左右相机的投影中心之间的平移向量就是左极点方向,则构造e1为
x映射方向
下一个矢量应该和e1正交,选择沿着图像平面且正交于光轴的方向比较好
y映射方向最后的就很简单了,叉乘就完事了
z映射方向
校正矩阵就构造完毕了。最后使用这个下面这个矩阵对图像平面进行变换就可以实现行对准了。
完毕
重投影矩阵可以将图像平面中的二维点映射回物理世界中的三维坐标。这里不加证明地给出重投影矩阵的定义
重投影矩阵
参数来自左侧视图,如果光轴相交于无穷远,则右下角的项应该为0。再给定视差d,则可以投影到物理世界了。
使用重投影矩阵
最后结果
三维坐标
通过以上矫正方法,就能得到理想的立体成像装置了,就像最开始那幅图一样。
立体匹配
立体校正过后就是立体匹配这个步骤了。OpenCV实现了两个算法,一个是块匹配算法(block matching, BM),一个是半全局块匹配算法(semi-global block matching, SGBM)。这两种方法是互补的,BM比较快,但精确度有限;SGBM则比较慢,但效果比较好。
这两个算法比较复杂,感觉书上并没有讲清楚。笔者参阅了一些论文和博客,但仍尚未完全理解。尤其是SGBM算法,使用到了信息熵,以及动态规划的思想。之前学过数据结构,但没学到动态规划。这里先留个坑,等我把基础补上去再回过头来总结一下。
有能力的读者可以参考一下最后贴出的论文,我个人是看的有点晕,还是需要继续学习啊- -!
来自三位重投影的深度映射
假设得到了视差d,那得到深度映射就是轻而易举了,用上上面提到的重投影矩阵
使用重投影矩阵
就可以从视差图转换到深度映射
视差图,灰度越深越视差越小,变换一下就可以得到深度了暂时就到这里吧。感觉给自己开了好多坑,幸好总体课不多,还是很有信心把坑都填上的 -.-
Reference:
Small Vision Systems: Hardware and Implementation —— Kurt Konolige
(opencv中 BM算法实现 )
Stereo Processing by SemiglobalMatching and Mutual Information —— Heiko Hirschmu¨ller(SGBM算法)
学习opencv3(中文版) —— Adrian Kaehler & Gary Bradski
向量叉乘与叉乘矩阵