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

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

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

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

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

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

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

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

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

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

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

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

我们在上图中加点东西,左边两个点为两个相机的光心 C C C,右边的一个点为空间点 P P P,在光心前面加上像平面 I I I(我在前面博文中就已经说过,像平面的其实是在光心的后方,拿到前面来是等价的,但是理解起来更直观一些)。空间点和光心的连线与像平面的交点为 p p p
在这里插入图片描述
从另一个角度来说, p p p是空间点 P P P在图像上的投影点,也就是我们在图像上看到物体的的成像。

好了,回到前面的问题,怎么确定射线 C 1 P , C 2 P C_1P,C_2P C1P,C2P呢?显然,图中有一个很明显的恒等关系是, C 1 P ≡ C 1 p 1 , C 2 P ≡ C 2 p 2 C_1P\equiv C_1p_1,C_2P\equiv C_2p_2 C1PC1p1,C2PC2p2,所以确定射线 C 1 P , C 2 P C_1P,C_2P C1P,C2P可以转换成确定射线 C 1 p 1 , C 2 p 1 C_1p_1,C_2p_1 C1p1,C2p1 C 1 , C 2 C_1,C_2 C1,C2我们已经通过标定得到了,而 p 1 , p 2 p_1,p_2 p1,p2的确定过程就称为匹配了。一般情况下,我们给定一个像素 p 1 p_1 p1,在另外一个视图中寻找对应的匹配点 p 2 p_2 p2,找到了就可以计算 P P P了。

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

为什么研究对极约束

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

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

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

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

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

极平面和极线

对极约束是怎么来的呢?我们看下图:
在这里插入图片描述

图1 对级约束

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

那怎么确定这条直线呢?我们已知 O 1 , O 2 , p O_1,O_2,p O1,O2,p,可以计算平面 O 1 p O 2 O_1pO_2 O1pO2的方程,它和像平面 I 2 I_2 I2(就是 p 2 p_2 p2所在的像平面)相交的直线即为 l 2 l_2 l2,有了 l 2 l_2 l2的方程就可以在像平面 I 2 I_2 I2里挨个遍历位于线 l 2 l_2 l2上的像素了。在稀疏点匹配里,我们就可以这样做从而提高搜索效率。

极线校正

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

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

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

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

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

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

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

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

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

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

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

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

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

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

如下图所示,纠正后的像平面,水平 u u u轴和基线 C 1 C 2 C_1C_2 C1C2平行,焦距 f f f和主点坐标相等。
在这里插入图片描述

图3 Fusiello极线校正
具体地,第一步是旋转相机让像平面共面且平行于相机基线,实际上是重新定义一个相机坐标系,所以我们首先来看新相机坐标系如何设计:
  1. 首先是 X X X轴,显然要和相机基线平行,才能让像平面平行于相机基线,所以 X X X轴基向量为 r x = ( C 2 − C 1 ) / ∣ ∣ C 2 − C 1 ∣ ∣ r_x=(C_2-C_1)/||C_2-C_1|| rx=(C2C1)/C2C1
  2. 其次是 Y Y Y轴,它是和 X X X轴正交的,可以设置一个任意的单位向量 k k k,让Y轴和 X X X轴以及向量 k k k正交,所以 Y Y Y轴的基向量为 r y = k × r x r_y=k\times r_x ry=k×rx。关于这个 k k k,理论上任意都可以,但是我们希望新坐标系下的图像和原图的范围尽量一致,所以尽量选择和旧的 Y Y Y轴近似的朝向,在Fusiello法中, k k k为旧的 Z Z Z轴所表示的单位向量。
  3. 最后是 Z Z Z轴, X X X Y Y Y轴确定后, Z Z Z轴的基向量就可以通过两者的叉乘基于右手法则得到了: r z = r x × r y r_z=r_x \times r_y rz=rx×ry

确定了新坐标系的3个基向量,就可以确定新的旋转矩阵
R n = [ r x T r y T r z T ] R_n=\left[\begin{matrix}r_x^{\text T}\\r_y^{\text T}\\r_z^{\text T}\end{matrix}\right] Rn=rxTryTrzT

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

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

确定 K K K R R R后,我们得到新的投影矩阵 M n = K n [ R n ∣ − R n C ] M_n=K_n[R_n|-R_nC] Mn=Kn[RnRnC]

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

目前来说,我们旋转了相机以及重定义内参,这样变换了旋转矩阵 R → R n R\rightarrow R_n RRn和内参矩阵 K → K n K\rightarrow K_n KKn,而没有改变的是相机中心 C C C。所以我们现在有新旧两组投影矩阵
M = K [ R , − R C ] = [ Q ∣ − Q C ] M n = K n [ R n , − R n C ] = [ Q n ∣ − Q n C ] \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,RnC]=[QQC]=[QnQnC]

其中, Q = K R , Q n = K n R n Q=KR,Q_n=K_nR_n Q=KR,Qn=KnRn

假设空间中的一点 P P P,它在新旧投影矩阵下的投影表达式分别为:
λ p = M P = [ Q ∣ − Q C ] P λ n p n = M n P = [ Q n ∣ − Q n C ] P \begin{aligned} \lambda p&=MP&&=[Q|-QC]P\\ \lambda_n p_n&=M_nP&&=[Q_n|-Q_nC]P \end{aligned} λpλnpn=MP=MnP=[QQC]P=[QnQnC]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 ) p n = Q n ( P − C ) \begin{aligned} p&=Q(P-C)\\ p_n&=Q_n(P-C) \end{aligned} ppn=Q(PC)=Qn(PC)

可得:
p n = Q n Q − 1 p p_n=Q_nQ^{-1}p pn=QnQ1p

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

对于两个相机,根据公式可以计算各自的转换矩阵 T 1 , T 2 T_1,T_2 T1,T2

优缺点

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

但是也存在一定的缺点,其为新的相机指定一样的内参,其实对于夹角比较大的双相机系统来说不太合理,如图3所示,在保持主点位置约等于旧主点位置的情况下,对于原先有较大夹角的像对,重叠区显著减少了,这是我们不想看到的,而如果你为双相机设置不同的主点坐标(具体来说是主点的 x x x坐标),则情况就可以改善了,如下图所示:
在这里插入图片描述
至于这个主点的调整量分别是多少,和你的相机设计有关,如果你是一个双相机立体系统,则建议你可以先按照Fusiello来设计内参,但把图像的宽设置得尽量比原始宽大一些,再把结果可视化,设计交互做图像裁剪,裁剪范围确定后可得到新的主点坐标。因为双目结构是固定的,所以你只需调整一次,后面如果不动结构就不用再调整了。

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

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

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

大家拜拜!点赞收藏关注哦!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/rs_lys/article/details/119837782