《Learning OpenCV3》ch19:双目标定与立体匹配

简介: 上一章讲到一些射影几何和单摄像机参数标定的内容,主要还是为了这一章的内容来服务。我们会用到18章的一些概念,比如说内参数矩阵M,畸变参数,旋转矩阵等内容。

上一章讲到一些射影几何和单摄像机参数标定的内容,主要还是为了这一章的内容来服务。我们会用到18章的一些概念,比如说内参数矩阵M,畸变参数,旋转矩阵等内容。

目前来说,还没有可靠的方法能够在单幅图像的情况下进行标定和提取三维信息。在立体视觉中,通过把从不同摄像机同时获取的两个或更多的图像的特征,与其他图像中的相关特征进行匹配,分析视差,产生深度信息。


img_25907b501cc21be34cbbfe43acba84fe.png
双目摄像头标定

立体成像

使用双目摄像机进行立体成像包括四个步骤:

  1. 使用数学的方法消除透镜畸变,上一章已经提到。

  2. 调整摄像机之间的位置和距离,并根据标定图像来进行计算。这一步称为“标定”。

  3. 在两个摄像头得到的图像中寻找相同的特征,得到视差d,这一步称为“匹配”。

  4. 通过三角测量的方法将视差图转化为深度图,这一步称为“重投影”。

我们从最后一步开始,然后分析前三个步骤。

三角测量

想象一个理想的立体装置,图像没有畸变,图像平面共面,光轴平行,焦距相同,主点已经被校准到该有的位置(没有接触过这些概念的可以看我的另一篇读书笔记)。

此外,假设摄像机前向平行排列,即每一个像素行和另一个摄像机中的像素行精确地对齐,并能够在物理世界中找到一点P,在左右图像中分别有成像点。那么,通过相似三角形可以得到深度Z。

img_893023e4a73a69872afb46cefbf430ab.png
理想设备

img_91a24278ffc7a934865160cbb2ed22e4.png
相似三角形

Obviously,由公式可知,视差与深度成反比,并且存在非线性关系。也就是说,当视差趋近于零时,微小的变化不会对深度有太大的影响,反之亦然。可以得出结论,立体视觉系统只有在屋里与摄像机距离比较近时才有比较高的深度分辨率。

img_a3760bd0e9379a560ba2008035aa84d4.png
深度与视差成反比

用于立体视觉中OpenCV的二维和三维坐标系如下。


img_bffe6da797046133ea16b010e2d1f643.png
坐标系如上

了解简化模型之后,就要讨论丑陋的现实模型了。现实世界中摄像机不会严格地前向平行对准,虽然可以通过数学的方法矫正图像,但还是要尽量对准,这样使数学变换更容易处理。

并且为了得到更好的结果,需要同步摄像机,即在同一时刻捕获图像,那么物体如果移动,就会出现问题。我们的目标是从数学上将两个摄像机对准到一个观察平面,使得摄像机之间的像素行使彼此精确对准的。


img_a6adef4a4df8ade2d023b18f45198c67.png
真实情况

对极几何

之前搞全景图像拼接的时候用到过,可以看看这篇文章。图中的连接投影中心的直线与投影平面(projective plane)的交点称为极点(epipole),连接投影点和极点的虚线称为极线(epipolar line)。两条极线显然是共面的,称为极面

img_a0eabd8828ecc131bcb9536000ebfb63.png
对极几何

根据推导和几何领域的公理,我们得出以下结论:

  • 摄像机视图中的每一个三维点(图中的点P)都被包含在与每个图像相交的极面中。两者产生的直线是极线。

  • 给定一幅图像上的特征点,在另一个图像中相匹配的点一定位于对应的极线上,这被称为“极线约束”

  • 极线约束意味着,一旦我们知道了立体实验设备之间的对极几何,在两幅图像之间匹配特征的二维搜索可以转变为沿着极线的一维搜索(在应用三角测量原理的时候)。这不仅会极大地节省计算成本,同时会帮助我们排除许多可能会产生虚假匹配的点。

本征矩阵和基本矩阵

本征矩阵E包含关于物理空间中两个摄像机的平移和旋转的信息。基本矩阵(基础矩阵)F除了包含相同的信息外,矩阵F还包含两个摄像机的内参数,他可以在像素坐标系上将两台摄像机关联。

img_fb55b277c09ca919f2a07bab3b88661f.png
平移和旋转

接下来就要讨论一下公式推导的问题了。

具体的思路是用我们已知的极面来把所有这些关联起来。设法向量n,x为极面上的任意一点,a为极面上的固定点,则有


img_738640d54a35eab0e61633cb73f1e4b0.png
法向量垂直于相应平面

可以用叉乘的方式构造法向量,如下

img_0fd8fe4b2e970683ae90ba93d5af4db4.png
叉乘得到一个垂直的向量

我们可以将已经知道的等式变换一下


img_6ab0ec59d2586e449efadb830721e9bb.png
回想一下上面的图
img_db252e25dca634d38d7a11cd5315f3ed.png
简单变换

上一章讲到,旋转矩阵为对称阵,则有

img_f8c7c8c93c547a46628097c736057543.png
对称矩阵

跟据上述条件,则得到


img_15dd83418a6fd5a3d594db07723edb25.png
带入上上上上式

根据线代知识,我们可以讲叉乘写成一个矩阵乘法的形式


img_f4d5df14771abdacc0e8351d24bd345f.png
叉乘转换成矩阵乘法

印象中线代老师好像没讲这个。可以看看这篇博客,其实推导挺简单的

将这个条件回代,得到一个重要结论

img_0df435b9c5354d18c3657ca87716e767.png
重要结论

点乘R·S就是我们对本征矩阵E的定义


img_3ffd48d10dd032659f9fccbfd56d6349.png
最终结论

实际使用中,我们需要的是投影平面上的观察到的点。我们可以利用投影公式


img_32cbff625f555e741e4dd45c54b873d3.png
回忆一下相机模型

则最终结论的左边可以变成


img_5f6997d9bbff1ae39075c8a03ba14e02.png
实际使用

看似我们可以通过基础矩阵来将左边的成像点映射到另一边,但很遗憾的是,E是一个秩亏矩阵(一个秩为2的3x3矩阵),所以只能将一个点映射到一条直线上。

矩阵E包含两个摄像机相关的所有几何信息,但不包括相机的内部参数。上面推导中的向量p只是几何意义上的点,通过下式跟像素点关联起来

img_98385b14be5a0f04d3f1914687eecb09.png
M为内参矩阵

则根据前面的推导结论,可以得到

img_60fdcb903aba724304016a3ed1e64413.png
有点丑

那么中间的一坨就是基本矩阵的定义


img_41b2a700bdd8c16bec6a0f53c1ce6b48.png
基本矩阵

实际使用中就可以这样用


img_25c2e0d92b61901c8ac477ef68d6b45e.png
基本矩阵的最终推导

简而言之,基本矩阵F和本征矩阵E差别在于,基础矩阵在图像像素坐标中操作,本征矩阵E在物理坐标系中操作。相类似的,矩阵F的秩也为2

对于OpenCV中这两个玩意怎么计算,还是看我之前写的这篇文章

立体标定(Stereo Calibration)

讲到这里,就该使用棋盘进行立体标定了。

书的中文版中将 Stereo Calibration 翻译成立体校正,这个很奇怪,按道理说应该是立体标定。后面讲到 Stereo Rectification 的时候又翻译成立体校正,估计前面是错的,后面才是正确的。

具体实现跟单目标定差不多。除了计算出矩阵E和F,还需要计算出两个摄像机之间的旋转矩阵R和平移向量T。方法是分别计算出两个摄像机的R和T,再由以下公式计算


img_8e10509bd817419e13c5de565de42c75.png
旋转

img_f9c7c6671e6cd717c8db94dbd7af6a80.png
平移

立体矫正(Stereo Rectification)

正如之前说到,不存在理想的前线平行对准。那么立体矫正的目的就在于:将两个摄像机的像平面重新映射,使两者位于完全相同的平面上,图像行完全对准到前向平行对准。

经过标定和矫正,我们希望两个摄像机之间的图像行是对准的,以使立体对应(在两个不同摄像机视图中找到同一个点可靠和计算容易。

OpenCV中实现了两个立体矫正算法:1)Hartley算法,只使用基本矩阵产生非标定立体视觉;2)Bouguet算法,使用两个标定摄像机中的旋转和平移参数。一般使用Bouguet算法,这里只讨论这个。算法的主要思想如下:

  • 计算出来的旋转矩阵R切成两半,左图像旋转一半,右图像旋转一半,这样重投影畸变会比较小。

  • 为了使极线平行对准,我们需要将极点变换到无穷远并使极线平行对准的矩阵Rrect。


    img_c9b0364433703dcea4349c0a6f7ae2cd.png
    把旋转矩阵砍一半

    img_52d1181a03dd474a9d71e7f826c6f078.png
    把旋转矩阵砍一半

设一个可以将极点变换到无穷远的矩阵如下


img_a321961567e36e9a53160d0e44f1c00c.png
校正矩阵

左右相机的投影中心之间的平移向量就是左极点方向,则构造e1为


img_14946e77c064a4f22533e7298c24d9d4.png
x映射方向

下一个矢量应该和e1正交,选择沿着图像平面且正交于光轴的方向比较好

img_c54ba9288daee969588fb2d791508fbf.png
y映射方向

最后的就很简单了,叉乘就完事了


img_ea62872a374d6fa88f5c87e4faef7ce4.png
z映射方向

校正矩阵就构造完毕了。最后使用这个下面这个矩阵对图像平面进行变换就可以实现行对准了。


img_c7175f2573bd0265758f09b33d35337f.png
完毕

重投影矩阵可以将图像平面中的二维点映射回物理世界中的三维坐标。这里不加证明地给出重投影矩阵的定义


img_8acbf6cbbbe25104db9fffe170ca328d.png
重投影矩阵

参数来自左侧视图,如果光轴相交于无穷远,则右下角的项应该为0。再给定视差d,则可以投影到物理世界了。


img_8be4c97a32bd66d7749bcb145277dbdf.png
使用重投影矩阵

最后结果
img_02c299a78d5c0c6b05aa7a59048e4a8c.png
三维坐标

通过以上矫正方法,就能得到理想的立体成像装置了,就像最开始那幅图一样。

立体匹配

立体校正过后就是立体匹配这个步骤了。OpenCV实现了两个算法,一个是块匹配算法(block matching, BM),一个是半全局块匹配算法(semi-global block matching, SGBM)。这两种方法是互补的,BM比较快,但精确度有限;SGBM则比较慢,但效果比较好。

这两个算法比较复杂,感觉书上并没有讲清楚。笔者参阅了一些论文和博客,但仍尚未完全理解。尤其是SGBM算法,使用到了信息熵,以及动态规划的思想。之前学过数据结构,但没学到动态规划。这里先留个坑,等我把基础补上去再回过头来总结一下。

有能力的读者可以参考一下最后贴出的论文,我个人是看的有点晕,还是需要继续学习啊- -!

来自三位重投影的深度映射

假设得到了视差d,那得到深度映射就是轻而易举了,用上上面提到的重投影矩阵


img_8be4c97a32bd66d7749bcb145277dbdf.png
使用重投影矩阵

就可以从视差图转换到深度映射

img_e7ef4fb7b23eb66f8313c6ea180f470c.png
视差图,灰度越深越视差越小,变换一下就可以得到深度了

暂时就到这里吧。感觉给自己开了好多坑,幸好总体课不多,还是很有信心把坑都填上的 -.-

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
向量叉乘与叉乘矩阵

目录
相关文章
|
算法 计算机视觉
《Learning OpenCV3》ch18:相机模型与标定
省赛期间用到双目视觉的时候,只是很粗浅地调用了下API,毕竟初学而且时间紧迫。最近打算跟一个硕士生再做一个相关项目,而且也想用Stereo Vision作为毕业设计,所以很有必要了解一下其中的原理。
3158 0
|
1月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
338 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
2月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
49 4
|
2月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
3月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
WK
|
3月前
|
编解码 计算机视觉 Python
如何在OpenCV中进行图像转换
在OpenCV中,图像转换涉及颜色空间变换、大小调整及类型转换等操作。常用函数如`cvtColor`可实现BGR到RGB、灰度图或HSV的转换;`resize`则用于调整图像分辨率。此外,通过`astype`或`convertScaleAbs`可改变图像数据类型。对于复杂的几何变换,如仿射或透视变换,则可利用`warpAffine`和`warpPerspective`函数实现。这些技术为图像处理提供了强大的工具。
WK
109 1
|
5月前
|
算法 计算机视觉
【Qt&OpenCV 图像的感兴趣区域ROI】
【Qt&OpenCV 图像的感兴趣区域ROI】
169 1
|
5月前
|
运维 算法 计算机视觉
【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
【Qt&OpenCV 图像的模板匹配 matchTemplate/minMaxLoc】
79 1
|
5月前
|
存储 编解码 算法
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
91 0
|
4月前
|
机器学习/深度学习 XML 计算机视觉
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它提供了大量的函数和工具,用于处理图像和视频数据。