亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知距离,导航避障,从而翱翔于天地之间。而当今世界是智能化的世界,我们的科学家们探索各种机器智能技术,让机器能够拥有人类的三维感知能力,并希望在速度和精度上超越人类,比如自动驾驶导航中的定位导航,无人机的自动避障,测量仪中的三维扫描等,都是高智机器智能技术在3D视觉上的具体实现。

立体视觉是三维重建领域的重要方向,它模拟人眼结构用双相机模拟双目,以透视投影、三角测量为基础,通过逻辑复杂的同名点搜索算法,恢复场景中的三维信息。它的应用十分之广泛,自动驾驶、导航避障、文物重建、人脸识别等诸多高科技应用都有它关键的身影。

本课程将带大家由浅入深的了解立体视觉的理论与实践知识。我们会从坐标系讲到相机标定,从被动式立体讲到主动式立体,甚至可能从深度恢复讲到网格构建与处理,感兴趣的同学们,来和我一起探索立体视觉的魅力吧!

本课程是电子资源,所以行文并不会有太多条条框框的约束,但会以逻辑清晰、浅显易懂为目标,水平有限,若有不足之处,还请不吝赐教!
个人微信:EthanYs6,加我申请进技术交流群 StereoV3D,一起技术畅聊。
CSDN搜索 :Ethan Li 李迎松,查看网页版课程
随课代码,将上传至github上,地址:StereoV3DCode:https://github.com/ethan-li-coding/StereoV3DCode

让大家久等了,最近工作变动,尚在适应中,望大家海量!

在前面的博文中,我们已经介绍完了基础知识和相机标定,同学们一定想着下一步该往那个方向,在相机标定之后,相机的位姿就确定了,而接下来,拿着相机采集图像是自然会发生的事情,那采集完图像之后呢?我们该做什么呢?

回到立体视觉的最终目标,是通过对图像做双视匹配计算场景的三维坐标,在这入门系列,我不得不得提前解释下什么叫双视匹配,特别是匹配二字的含义。

匹配,英文是match,从字面意义来说,是将N(N>=2)个目标配到一起,这N个目标通常有一些共同或者近似的属性,比如一对耳机的左右两只,他们是同属于一副耳机,比如你和你的兄弟姐们,你们都是你爸妈的孩子。自然地,双视匹配,就是在两个视图中,寻找共同属性的像素点配成对,在立体视觉里,这个共同属性是:它们是空间中同一个点在各自视图的投影,也就是说它们代表了空间中的同一个点。

那为何要做双视匹配呢?这要从三角测量说起,

三角测量是非常简单的一个概念,指的是确定两个点和从两个点出发的射线,就可以计算出两条射线相交的另一个点坐标,三个点形成一个三角关系,所以叫三角测量。

对应到立体视觉里面,三个点分别是:两个相机的光心点和一个空间点,光心的位置通过标定确定,而两条射线是两光心各自和空间点的连线,如果再确定了两条射线,就可以计算出空间点的坐标,有人问,怎么确定两条射线呢?那就是匹配要干的事情了。

我们在上图中加点东西,左边两个点为两个相机的光心CCC,右边的一个点为空间点PPP,在光心前面加上像平面III(我在前面博文中就已经说过,像平面的其实是在光心的后方,拿到前面来是等价的,但是理解起来更直观一些)。空间点和光心的连线与像平面的交点为ppp。

从另一个角度来说,ppp是空间点PPP在图像上的投影点,也就是我们在图像上看到物体的的成像。

好了,回到前面的问题,怎么确定射线C1P,C2PC_1P,C_2PC1​P,C2​P呢?显然,图中有一个很明显的恒等关系是,C1P≡C1p1,C2P≡C2p2C_1P\equiv C_1p_1,C_2P\equiv C_2p_2C1​P≡C1​p1​,C2​P≡C2​p2​,所以确定射线C1P,C2PC_1P,C_2PC1​P,C2​P可以转换成确定射线C1p1,C2p1C_1p_1,C_2p_1C1​p1​,C2​p1​。C1,C2C_1,C_2C1​,C2​我们已经通过标定得到了,而p1,p2p_1,p_2p1​,p2​的确定过程就称为匹配了。一般情况下,我们给定一个像素p1p_1p1​,在另外一个视图中寻找对应的匹配点p2p_2p2​,找到了就可以计算PPP了。

好了,关于匹配的定义就说到这里。我们回到今天的主题:对极约束

为什么研究对极约束

在计算机科学中,给定一个确定的问题,一定会有各种算法从研究如何解决它,再上升到如何高效的解决它,而它们也不是依次进行,而是交叉地,即研究最确定解和研究最高效解是同步进行的。而对于匹配问题而言,寻找对应匹配点对这个问题,实在不是个简单问题,几十年来,没有一个算法能完美寻找所有正确匹配点对,角度产生的图像之间的仿射扭曲、弱纹理、重复纹理、暗光、过曝、透明等等,头疼的问题确实非常多,而且有些看上去是无解的,但这丝毫不妨碍众多学者们研究对该问题的浓厚兴趣,从而产生了很多优秀的算法,有很多在实际工程应用中被证明是精确且高效的(这里的精确并不是说它们是几何意义上的精确,而是说工程意义上的精确)。

回到正题,熟悉一点优化思想的人都知道,一旦涉及到搜索空间这个词,就会有人自然而然的想到如何减少搜索空间来提高搜索效率,毕竟我们的计算机是三维空间的人设计的,它的运动也准循着三维空间的规律,没有高维空间折叠能力,在搜索这件事上还是要受限制于空间的大小和距离,但是我们可以也做几件事情:

  1. 让它的运动空间变小。
  2. 让它在不存在目标点的位置少做停留。

我们的对级约束就是为了做第一件事,让匹配的搜索空间变小,略去完全不可能是解的像素。简单来说,作为匹配对的两个像素,一定会满足一个约束公式,如果不满足则肯定不是匹配点。这样可以省去非常多的无意义搜索,但稍显遗憾的是,这个约束不是唯一约束,也就是说对于左视图上一个像素点,在右视图上还是会有很多像素满足这个约束,所以只能缩小搜索空间,不能直接确定解。

对极约束,是将搜索空间约束到像平面内的一条直线上,这个我们下面慢慢来说。

极平面和极线

对极约束是怎么来的呢?我们看下图:

图1 对级约束

光心O1,O2O_1,O_2O1​,O2​(原谅我换了个符号)和空间点PPP形成一个三角关系,实际上它们确定了一个空间平面,这个平面和两个像平面都相交,交线分别是l1,l2l_1,l_2l1​,l2​,发挥我们的想象力,很容易发现,在l1l_1l1​上的所有点,他的匹配点一定在l2l_2l2​上,这就是对极约束,它将匹配的搜索空间限制到了一条直线上,大大减少了搜索的空间大小,提高匹配效率。而两条直线l1,l2l_1,l_2l1​,l2​就叫做极线,我们可以称它们两为极线对。这个概念大家记一下,后面会出现。

那怎么确定这条直线呢?我们已知O1,O2,pO_1,O_2,pO1​,O2​,p,可以计算平面O1pO2O_1pO_2O1​pO2​的方程,它和像平面I2I_2I2​(就是p2p_2p2​所在的像平面)相交的直线即为l2l_2l2​,有了l2l_2l2​的方程就可以在像平面I2I_2I2​里挨个遍历位于线l2l_2l2​上的像素了。在稀疏点匹配里,我们就可以这样做从而提高搜索效率。

极线校正

好了,上面我们讲了对级约束,大家明白了它的概念和空间意义,下面我还要讲一个重要的概念:极线校正,同样要问一句,为什么要讲它,在上面一章中我们提到,对级约束可以让我们减小搜索空间,有了对级约束,对于左视图的一个像素点p1p_1p1​,可以计算出右视图中匹配点p2p_2p2​所在的那条极线l2l_2l2​,从而在l2l_2l2​上搜索正确解。听上去确实不错,大大减少了搜索空间,但它还是存在一个缺点,就是对于左视图的每个待匹配像素,都要计算它对应的那条极线,如果我的待匹配像素非常多(这正是稠密匹配的研究方向:逐像素匹配),那计算量还是挺大的。

有没有一种方法,可以不用计算,直接确定右边的极线呢?

答案当然是有,极线校正就是来回答这个问题!

还是观察上图,我们会进一步发现,极线l1l_1l1​上的所有像素和l2l_2l2​上的像素满足同一种约束公式呢,也就是说极线l1l_1l1​上的所有像素,算出的对应极线,都是同一条l2l_2l2​。究其原因,是因为它们都属于同一个极平面呀!所以可以这样认为,一个极平面就可以在两个视图上找到一对极线,这对极线上的所有像素满足同一个约束公式,而多个极平面就产生了多个极线对,众多的极线对可以涵盖图像上的所有像素点!

进一步,我们可以将这些极线对上的像素重排列在像平面,同一对极线上的像素排列到同一行,这样我们就可以通过行号来确定同一极线对的像素,不用在计算极线方程了。简言之,左视图像素p1p_1p1​的匹配点一定位于右视图行号相同的那一行像素内。

以上是对于极线校正的一个简单的意义解释。而从几何上来说,我们有更专业的解释:

极线校正是通过对两个相机进行旋转,并重新定义新的像平面,让极线对共线且平行于像平面的某条坐标轴(通常是水平轴),该操作同时建立了新的立体像对。纠正完成后,同一匹配点对,位于两个视图的同一行内,这意味着它们只有水平坐标(或者说列坐标)的差异,这个差异称为视差(简写ddd),数学定义上,视差d=col(p1)−col(p2)d=col(p_1)-col(p_2)d=col(p1​)−col(p2​)(colcolcol指水平方向坐标,或者说列坐标$)

图2 极线校正 *图片来源:Mattoccia S , Updates S M , Outline S M . Stereo Vision: Algorithms and Applications[J]. 2011.*

这个操作使得稠密匹配变得容易很多,当然,只是相对容易了。

解释完极线校正的概念和意义,我们关心的另一件事是,如何做极线校正?

这就有不同的方式来完成,今天我们主要来讲一讲Fusiello校正法

我们先来看看我们的目标:

  1. 极线对平行于某条坐标轴。
  2. 极线对共线,匹配点对位于像平面的同一行。

为达到这两个目标,我们要进行不同分析,前面说到,极线校正是通过旋转相机和重新定义像平面来做,实际上,两个操作的本质在于重新定义投影矩阵M=K[R∣−RC]M=K[R|-RC]M=K[R∣−RC]。通过旋转相机重定义旋转矩阵R→RnR\rightarrow R_nR→Rn​让新的像平面共面且平行于相机基线,则可以满足目标1,而重定义像平面的内参K→KnK\rightarrow K_nK→Kn​使双相机有同样的内参数,可以满足目标2。

如下图所示,纠正后的像平面,水平uuu轴和基线C1C2C_1C_2C1​C2​平行,焦距fff和主点坐标相等。

图3 Fusiello极线校正 具体地,第一步是旋转相机让像平面共面且平行于相机基线,实际上是重新定义一个相机坐标系,所以我们首先来看新相机坐标系如何设计:

  1. 首先是XXX轴,显然要和相机基线平行,才能让像平面平行于相机基线,所以XXX轴基向量为rx=(C2−C1)/∣∣C2−C1∣∣r_x=(C_2-C_1)/||C_2-C_1||rx​=(C2​−C1​)/∣∣C2​−C1​∣∣。
  2. 其次是YYY轴,它是和XXX轴正交的,可以设置一个任意的单位向量kkk,让Y轴和XXX轴以及向量kkk正交,所以YYY轴的基向量为ry=k×rxr_y=k\times r_xry​=k×rx​。关于这个kkk,理论上任意都可以,但是我们希望新坐标系下的图像和原图的范围尽量一致,所以尽量选择和旧的YYY轴近似的朝向,在Fusiello法中,kkk为旧的ZZZ轴所表示的单位向量。
  3. 最后是ZZZ轴,XXX和YYY轴确定后,ZZZ轴的基向量就可以通过两者的叉乘基于右手法则得到了:rz=rx×ryr_z=r_x \times r_yrz​=rx​×ry​

确定了新坐标系的3个基向量,就可以确定新的旋转矩阵
Rn=[rxTryTrzT]R_n=\left[\begin{matrix}r_x^{\text T}\\r_y^{\text T}\\r_z^{\text T}\end{matrix}\right]Rn​=⎣⎡​rxT​ryT​rzT​​⎦⎤​

关于这点,可以看下我前面的博文从基变换的角度理解旋转矩阵R。

第二步,是重新设计新的内参矩阵KnK_nKn​,理论上,KKK是可以任意设置的,但是为了和旧相机尽量保持一致,Fusiello法选择的是Kn=(Kleft+Kright)/2K_n=(K_{left}+K_{right})/2Kn​=(Kleft​+Kright​)/2。且把倾斜因子sss设置为0。

确定KKK和RRR后,我们得到新的投影矩阵Mn=Kn[Rn∣−RnC]M_n=K_n[R_n|-R_nC]Mn​=Kn​[Rn​∣−Rn​C]。

接下来就是校正过程,具体的过程是对于新图像像素pnp_npn​,通过变换矩阵TTT计算旧图像上的像素ppp:p=Tpnp=Tp_np=Tpn​,再通过双线性内插获取像素值赋给新图像。所以关键就在于如何得到变换矩阵TTT。

目前来说,我们旋转了相机以及重定义内参,这样变换了旋转矩阵R→RnR\rightarrow R_nR→Rn​和内参矩阵K→KnK\rightarrow K_nK→Kn​,而没有改变的是相机中心CCC。所以我们现在有新旧两组投影矩阵
M=K[R,−RC]=[Q∣−QC]Mn=Kn[Rn,−RnC]=[Qn∣−QnC]\begin{aligned} M&=K[R,-RC]&&=[Q|-QC]\\ M_n&=K_n[R_n,-R_nC]&&=[Q_n|-Q_nC] \end{aligned}MMn​​=K[R,−RC]=Kn​[Rn​,−Rn​C]​​=[Q∣−QC]=[Qn​∣−Qn​C]​

其中,Q=KR,Qn=KnRnQ=KR,Q_n=K_nR_nQ=KR,Qn​=Kn​Rn​。

假设空间中的一点PPP,它在新旧投影矩阵下的投影表达式分别为:
λp=MP=[Q∣−QC]Pλnpn=MnP=[Qn∣−QnC]P\begin{aligned} \lambda p&=MP&&=[Q|-QC]P\\ \lambda_n p_n&=M_nP&&=[Q_n|-Q_nC]P \end{aligned}λpλn​pn​​=MP=Mn​P​​=[Q∣−QC]P=[Qn​∣−Qn​C]P​

因为等式都是齐次表达式(p=[u,v,1],P=[X,Y,Z,1]p=[u,v,1],P=[X,Y,Z,1]p=[u,v,1],P=[X,Y,Z,1]),所以λ\lambdaλ可以都设置为1。上式展开得
p=Q(P−C)pn=Qn(P−C)\begin{aligned} p&=Q(P-C)\\ p_n&=Q_n(P-C) \end{aligned}ppn​​=Q(P−C)=Qn​(P−C)​

可得:
pn=QnQ−1pp_n=Q_nQ^{-1}ppn​=Qn​Q−1p

这就是新旧图像的转换公式,而T=QnQ−1T=Q_nQ^{-1}T=Qn​Q−1即是转换矩阵。

对于两个相机,根据公式可以计算各自的转换矩阵T1,T2T_1,T_2T1​,T2​。

优缺点

Fusiello法原理很简单,计算复杂度低,且可以高度并行,是一个不错的算法。

但是也存在一定的缺点,其为新的相机指定一样的内参,其实对于夹角比较大的双相机系统来说不太合理,如图3所示,在保持主点位置约等于旧主点位置的情况下,对于原先有较大夹角的像对,重叠区显著减少了,这是我们不想看到的,而如果你为双相机设置不同的主点坐标(具体来说是主点的xxx坐标),则情况就可以改善了,如下图所示:

至于这个主点的调整量分别是多少,和你的相机设计有关,如果你是一个双相机立体系统,则建议你可以先按照Fusiello来设计内参,但把图像的宽设置得尽量比原始宽大一些,再把结果可视化,设计交互做图像裁剪,裁剪范围确定后可得到新的主点坐标。因为双目结构是固定的,所以你只需调整一次,后面如果不动结构就不用再调整了。

今天就介绍到这吧,大家有疑问可以在留言区留言哦!

关于Fusiello法的网址,可以看Epipolar Rectification. by Andrea
Fusiello

下面是作者提供的一段伪代码,实在是很简单,没必要我再实现一遍了
https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/FUSIELLO2/node5.html

大家拜拜!点赞收藏关注哦!

立体视觉入门指南(6):对级约束与Fusiello法极线校正相关推荐

  1. 立体视觉入门指南:对级约束与Fusiello法极线校正

    作者丨李迎松@知乎 来源丨https://zhuanlan.zhihu.com/p/466758105 编辑丨3D视觉工坊 亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知 ...

  2. 立体视觉入门指南(4):相机标定之DLT直接线性变换【建议收藏】

    亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知距离,导航避障,从而翱翔于天地之间.而当今世界是智能化的世界,我们的科学家们探索各种机器智能技术,让机器能够拥有人类的三维感 ...

  3. 立体视觉入门指南:相机标定之Zhang式标定法

    作者丨李迎松@知乎 来源丨https://zhuanlan.zhihu.com/p/378819083 编辑丨3D视觉工坊 亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知 ...

  4. 立体视觉入门指南(5):双相机标定【再不收藏我收费了~】

    亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知距离,导航避障,从而翱翔于天地之间.而当今世界是智能化的世界,我们的科学家们探索各种机器智能技术,让机器能够拥有人类的三维感 ...

  5. 立体视觉入门指南(3):相机标定之张式标定法【超详细值得收藏】

    亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知距离,导航避障,从而翱翔于天地之间.而当今世界是智能化的世界,我们的科学家们探索各种机器智能技术,让机器能够拥有人类的三维感 ...

  6. 立体视觉入门指南(1):坐标系与相机参数

    亲爱的同学们,我们的世界是3D世界,我们的双眼能够观测三维信息,帮助我们感知距离,导航避障,从而翱翔于天地之间.而当今世界是智能化的世界,我们的科学家们探索各种机器智能技术,让机器能够拥有人类的三维感 ...

  7. 立体视觉入门指南(7):立体匹配

    关于立体匹配,我之前写了很多博客,重复去写就没有必要,学习的朋友请阅读如下链接. 本文我们随便聊聊立体匹配的方法论和弱纹理恢复问题. 文章目录 立体匹配系列 0 1 SGM系列 2 PatchMatc ...

  8. Microsoft Orleans 之 入门指南

    Microsoft Orleans 在.net用简单方法构建高并发.分布式的大型应用程序框架. 原文:http://dotnet.github.io/orleans/ 在线文档:http://dotn ...

  9. 生成对抗网络入门指南(内含资源和代码)

    python进阶教程 机器学习 深度学习 长按二维码关注 进入正文 前言:春节假期结束了,在这个假期中,原本好好的计划终究没能跟上变化,发生了很多意想不到的事情,导致公众号有近十天没能更新,首先给长期 ...

最新文章

  1. 微服务化后,这几点一定要注意
  2. 转:读AD里特殊的属性in C#
  3. cef使用缓存_CEF 文件下载功能实现
  4. Kali 2020版 Linux操作系统解决系统语言问题(英文--中文)
  5. 深拷贝浅拷贝的一些理解
  6. 坐标北京,Paddle Lite​ 线下交流会,助力算法落地​
  7. 11.Java 面试题整理(编程题)
  8. 【肌电信号】肌电信号处理系统含Matlab源码
  9. access更新查询非汉族加分_计算机二级Access:如何创建更新查询
  10. iOS开发-dSYM文件
  11. PC-DMIS 圆(环)型平面自动测量子程序
  12. 阿里云ecs服务器买完后可以更换操作系统么?
  13. html onload 写法,HTML onload用法及代码示例
  14. JDBC的操作步骤和实例
  15. Mysql ERROR: 1253 解决方法
  16. 示波器怎么当做记录仪用​
  17. 尹同跃捧走2022中国汽车年度人物;比亚迪当选2022最佳中国品牌汽车企业 | 美通社头条...
  18. 无锡设计培训——室内设计的前景
  19. 易点易动固定资产管理系统让行政和IT人员快速盘点固定资产
  20. 天猫双11为什么能抗住90秒100亿?消费狂欢背后隐藏了哪些架构技术?

热门文章

  1. 98% after emitting CopyPlugin vue启动停止的原因
  2. 亲民地理35期-雨中登泰山_我是亲民_新浪博客
  3. 解决:outlook邮件内容过宽,打印不全
  4. python函数ppt_如何用 Python 让你的PPT数据动起来
  5. 华为手机android7价格,华为7怎么样?报价多少?
  6. oracle omf管理,Oracle OMF文件管理
  7. MAC干净卸载IDEA
  8. 几何学五大公理_数学几何的五大公理、五大公设是什么??
  9. Keil 编译器AC6中的LLVM编译原理
  10. 实战技能分享,如何让工程代码各种优化等级通吃,含MDK AC5,AC6,IAR和GCC