ORB-SLAM3中双目匹配
主要流程
- 对右目点形成搜索表(key为该行r范围内的所有特征点)
- 对左目点进行遍历:
1、遍历在该位置的搜索表中右目的点(阈值 金字塔层级、minU、maxU)
2、使用描述子找到最相似的点作为锚点
3、在锚点附近进行图像块匹配,找到灰度1范数最小的块(11×11的)
4、进行二次函数拟合 - 排序并找到中值,按中值作为阈值选取一定范围内得匹配对
搜索表构建
对所有右目点进行遍历:对该特征点附近得行索引均加入该特征点
行索引 | Value |
---|---|
1 | 第1行附近得所有特征点 |
… | … |
n | 第n行附近得所有特征点 |
for(int iR=0; iR<Nr; iR++)
{
const cv::KeyPoint &kp = mvKeysRight[iR];// 右目特征点
const float &kpY = kp.pt.y;// 右目的列
const float r = 2.0f*mvScaleFactors[mvKeysRight[iR].octave];// 金字塔层级
const int maxr = ceil(kpY+r);// 宽度的阈值,在上下这个幅度限制内进行搜索
const int minr = floor(kpY-r);
for(int yi=minr;yi<=maxr;yi++)// 在范围内的行 都加入这个特征点
vRowIndices[yi].push_back(iR);
}
minU、maxU计算
参考slam14书中相机模型中的双目模型
对于双目模型公式 z = f b d z = \frac{fb}{d} z=dfb 和 d = u l − u r d = u_l - u_r d=ul−ur 进行稍微变换一下 u r = u l − d = u l − f b z u_r = u_l-d = u_l - \frac{fb}{z} ur=ul−d=ul−zfb 这样得话距离最近能测基线长度,最远是无穷大,带入进去就可以得到minU和maxU。
二次函数拟合
在进行像素块匹配后(这个过程有点像暴力光流操作)进行二次函数插值。设目前找到得最好位置是d
a ∗ d 2 + b ∗ d + c = d i s 2 a ∗ ( d − 1 ) 2 + b ∗ ( d − 1 ) + c = d i s 1 a ∗ ( d + 1 ) 2 + b ∗ ( d + 1 ) + c = d i s 3 a * d^2 + b *d + c = dis2 \\ a*(d-1 )^2 + b*(d-1) + c = dis1\\ a*(d+1)^2 + b*(d+1) + c = dis3 a∗d2+b∗d+c=dis2a∗(d−1)2+b∗(d−1)+c=dis1a∗(d+1)2+b∗(d+1)+c=dis3
- 利用2+3得到 a ( d 2 + 1 ) + 2 b ∗ d + 2 c = d i s 1 + d i s 3 a(d^2+1)+2b*d+2c = dis1+ dis3 a(d2+1)+2b∗d+2c=dis1+dis3 再在此式子减去2倍第一个式子得到 a = d i s 1 + d i s 3 2 − d i s 2 a = \frac{dis1+dis3}{2}-dis2 a=2dis1+dis3−dis2
- 利用3-2得到 b + 2 a ∗ d = d i s 3 − d i s 1 2 b+2a*d = \frac{dis3-dis1}{2} b+2a∗d=2dis3−dis1, 式子两端乘以 − 1 2 a -\frac{1}{2a} −2a1 (凑出 − b 2 a -\frac{b}{2a} −2ab形式、二次函数对称轴) 再把上一步得到得a带入。