Visual SLAM -- 理解对极几何和约束

双目立体视觉测量中,立体匹配(对应点的匹配 )是一项关键技术,对极几何在其中起着重要作用。双目立体视觉系统中,有两个摄像机在不同角度拍摄物理空间中的一实体点,在两副图像上分别有两个成像点。立体匹配就是已知其中的一个成像点,在另一副图像上找出该成像点的对应点。这样可以加快匹配的速度。

经典图

从上图看,如果得到三维点P在I1上的投影点如果是P1的话,那这个点在I2上的投影,一定会是在L2这条极线上。同理,相反的情况也是如此。

无论P1在O1P向量的哪个位置在I2上的投影都在L2这条极线上。根据对极几何的这个特性,我们就有了寻找两个匹配点的关系:

知道P1, P2在L2上找。知道P2,P1在L1上找。说的这些其实就是对极约束。

所谓对极约束就是说同一个点在两幅图像上的映射,已知左图映射点p1,那么右图映射点p2一定在相对于p1的极线上,这样可以减少待匹配的点数量。

对极约束的数学公式推导就不细说了,可以参考这篇

公式为 [公式] 。从这公式中我们记录 [公式] , [公式] 。我们有了极线方程后,就可以很快的判断三维点在图像中的投影是不是和P1匹配了。

ORB_SLAM2中有很好的应用:

bool ORBmatcher::CheckDistEpipolarLine(const cv::KeyPoint &kp1,const cv::KeyPoint &kp2,const cv::Mat &F12,const KeyFrame* pKF2)
{
    // Epipolar line in second image l = x1'F12 = [a b c]
    const float a = kp1.pt.x*F12.at<float>(0,0)+kp1.pt.y*F12.at<float>(1,0)+F12.at<float>(2,0);
    const float b = kp1.pt.x*F12.at<float>(0,1)+kp1.pt.y*F12.at<float>(1,1)+F12.at<float>(2,1);
    const float c = kp1.pt.x*F12.at<float>(0,2)+kp1.pt.y*F12.at<float>(1,2)+F12.at<float>(2,2);

    const float num = a*kp2.pt.x+b*kp2.pt.y+c;

    const float den = a*a+b*b;

    if(den==0)
        return false;

    const float dsqr = num*num/den;

    return dsqr<3.84*pKF2->mvLevelSigma2[kp2.octave];
}

该代码是在处理剔除不是很准确的匹配点。可以看到先获取了极线L,然后计算原本认为的匹配点kp2到这条极线的距离,如果没有小于一定的阀值就会别剔除。这样就可以计算出更为准确的匹配点,从而可以通过后续的三角测量计算出高质量的mappoint。