ORB-SLAM2 --- MapPoint::ComputeDistinctiveDescriptors 函数

目录

一、函数作用

二、函数步骤 

三、code 

四、函数解析 


一、函数作用

        计算地图点最具代表性的描述子。

        由于一个地图点会被许多相机观测到,因此在插入关键帧后,需要判断是否更新代表当前点的描述子,先获得当前点的所有描述子,然后计算描述子之间的两两距离,最好的描述子与其他描述子应该具有最小的距离中值。

二、函数步骤 

Step 1 获取该地图点所有有效的观测关键帧信息

Step 2 遍历观测到该地图点的所有关键帧,对应的orb描述子,放到向量vDescriptors中

Step 3 计算这些描述子两两之间的距离.

Step 4 选择最有代表性的描述子,它与其他描述子应该具有最小的距离中值

三、code 

void MapPoint::ComputeDistinctiveDescriptors()
{
    // Retrieve all observed descriptors
    vector<cv::Mat> vDescriptors;

    map<KeyFrame*,size_t> observations;

    // Step 1 获取该地图点所有有效的观测关键帧信息
    {
        unique_lock<mutex> lock1(mMutexFeatures);
        if(mbBad)
            return;
        observations=mObservations;
    }

    if(observations.empty())
        return;

    vDescriptors.reserve(observations.size());

    // Step 2 遍历观测到该地图点的所有关键帧,对应的orb描述子,放到向量vDescriptors中
    for(map<KeyFrame*,size_t>::iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++)
    {
        // mit->first取观测到该地图点的关键帧
        // mit->second取该地图点在关键帧中的索引
        KeyFrame* pKF = mit->first;

        if(!pKF->isBad())        
            // 取对应的描述子向量                                               
            vDescriptors.push_back(pKF->mDescriptors.row(mit->second));     
    }

    if(vDescriptors.empty())
        return;

    // Compute distances between them
    // Step 3 计算这些描述子两两之间的距离
    // N表示为一共多少个描述子
    const size_t N = vDescriptors.size();
	
    // 将Distances表述成一个对称的矩阵
    // float Distances[N][N];
	std::vector<std::vector<float> > Distances;
	Distances.resize(N, vector<float>(N, 0));
	for (size_t i = 0; i<N; i++)
    {
        // 和自己的距离当然是0
        Distances[i][i]=0;
        // 计算并记录不同描述子距离
        for(size_t j=i+1;j<N;j++)
        {
            int distij = ORBmatcher::DescriptorDistance(vDescriptors[i],vDescriptors[j]);
            Distances[i][j]=distij;
            Distances[j][i]=distij;
        }
    }

    // Take the descriptor with least median distance to the rest
    // Step 4 选择最有代表性的描述子,它与其他描述子应该具有最小的距离中值
    int BestMedian = INT_MAX;   // 记录最小的中值
    int BestIdx = 0;            // 最小中值对应的索引
    for(size_t i=0;i<N;i++)
    {
        // 第i个描述子到其它所有描述子之间的距离
        // vector<int> vDists(Distances[i],Distances[i]+N);
		vector<int> vDists(Distances[i].begin(), Distances[i].end());
		sort(vDists.begin(), vDists.end());

        // 获得中值
        int median = vDists[0.5*(N-1)];
        
        // 寻找最小的中值
        if(median<BestMedian)
        {
            BestMedian = median;
            BestIdx = i;
        }
    }

    {
        unique_lock<mutex> lock(mMutexFeatures);
        mDescriptor = vDescriptors[BestIdx].clone();       
    }
}

四、函数解析 

        判断该地图点是否是bad地图点,若不是则获取这个地图点的所有观测信息用临时变量observations保存,它是个map<KeyFrame*,size_t>类型的变量。

        存储的该地图点可以被哪些关键帧KeyFrame观测到,在这些关键帧中的索引size_t是多少。

        遍历观测到该地图点的所有关键帧observations,对应的orb描述子,放到向量vDescriptors中。

        计算这些描述子的两两距离存储到矩阵Distances中。

        假设这里的矩阵是4*4的。

\begin{bmatrix} a_{11} & a_{12} &a_{13} &a_{14} \\ a_{21} & a_{22}& a_{23}&a_{24} \\ a_{31}& a_{32}& a_{33} &a_{34} \\ a_{41}& a_{42}& a_{43}& a_{44} \end{bmatrix}

         即观测到该地图点的帧有4个,取出它们四个的描述子,a_{11}=a_{22}=a_{33}=a_{44}=0,即第一个描述子和第一个描述子的距离为0(自己和自己比较当然为0),a_{12}=a_{21},它们的数值等于第一个描述子和第二个描述子的汉明距离。

        我们有了描述子矩阵后,我们遍历每一行描述子矩阵,寻找每一行的距离中值,拿第一行来说,a_{11} ~a_{12} ~a_{13} ~a_{14}的中位数,遍历所有行,找到最小行的中位数以及它的行索引。

        将这个地图点最具代表性的描述子设置为最小的行的中位数索引对应的描述子。

        

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

APS2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值