即使是在同一数据集的同一张图像上,在不同时刻运行ORB-SLAM3,提取的特征点位置或数量都会存在一定随机性。比如我们要在第0帧上提取10000个特征点,第一次运行时,系统提取了10002个,第二次运行可能就变成了10004个。虽然这种微小的差异不会对系统运行产生影响,但会给调试带来不便。我们希望,不同时刻运行时,特征点的结果都是稳定的,即对于同一图像和配置文件,Frame
类的data member std::vector<cv::KeyPoint> mvKeys
存储的特征点信息是不变的。
问题出在函数vector<cv::KeyPoint> ORBextractor::DistributeOctTree()
中。这个函数将图像视作root node,将每个node分割成4个child node,不断迭代直到node的数量达到要求(比如10000)。之后从每个node中的fast角点里挑选出结果最好的那个,这样就保证了特征点的分布均匀。迭代中会对node按照包含角点的数量进行一次升序排序:
sort(vPrevSizeAndPointerToNode.begin(), vPrevSizeAndPointerToNode.end());
如果某些node包含相同数量的角点,那么每次排序的结果都会出现一定差异。通俗些,大家都有x个角点,按照数量排序,这次你在前,他在后,下次就是他在前,你在后。这种差异就导致了后续分割结果的随机性。解决这个问题也很容易,我们再写一个cmp()
函数指定排序方法:
bool cmp( pair<int,ExtractorNode*>& a, pair<int,ExtractorNode*>& b)
{
return a.first < b.first;
}
修改被调用的sort()
函数为:
sort(vPrevSizeAndPointerToNode.begin(), vPrevSizeAndPointerToNode.end(), cmp);
这样就保证了特征点提取结果的稳定,也方便后面的调试。