1.公有函数:
1 KeyFrame(Frame &F, Map* pMap, KeyFrameDatabase* pKFDB);
构造函数:输入进来一帧,该帧作为关键帧。将该帧传入地图、关键帧的集合。
2 void SetPose(const cv::Mat &Tcw);
cv::Mat GetPose();
cv::Mat GetPoseInverse();
cv::Mat GetCameraCenter();
cv::Mat GetStereoCenter();
cv::Mat GetRotation();
cv::Mat GetTranslation();
根据给的量设置公有变量,和获得公有量。
3 void ComputeBoW();
计算词袋,mBowVec,mFeatVec。上一篇讲过了,只是注意mFeatVec指定了层数。
4 void AddConnection(KeyFrame* pKF, const int &weight);
当前帧与传入的pKF(输入)有共视的时候,增加连接关系。weight(输入)。表示的是当前帧和pKF共同看到了多少个关键点。 这个函数改变的是公共变量: std::map<KeyFrame*,int> mConnectedKeyFrameWeights;
5 void EraseConnection(KeyFrame* pKF);
删除当前帧与关键帧pKF的连接关系,也是操作这个公共变量std::map<KeyFrame*,int> mConnectedKeyFrameWeights;完了之后记得跟新下,UpdayeBestCovisible.
6 void UpdateConnections();
主要是跟新,该帧与其他关键帧的连接关系。
第一步,找出这个关键帧里面的每一个地图点,并且找出其他同样也能看到这个地图点的关键帧们,跟新一下当前帧与其他关键帧的共视权重。直到找完当前帧的所有地图点。我们将结果放到一个容器里面 map<KeyFrame*,int> KFcounter;第一个表示当前帧与哪个关键帧有共视关系,第二个参数表示共视点的个数(权重)。
第二步:挑选出那些共视权重大于等于15的那些,放入容器vector<pair<int,KeyFrame*> > vPairs; 然后把vPair从大小进行排序。
第三步:更新最小生成树(将权重最大的那帧最为当前帧的父节点)
最后得到的结果:
1.得到公有变量mConnectedKeyFrameWeights,所有与当前帧有共视关系的关键帧及其权重。
2.得到公共变量:mvpOrderedConnectedKeyFrames :权重大于15的关键帧 按权重排列的vector向量。
3.得到公共变量:mvOrderedWeights :权重(大于15)从大到小排列的vector向量。
4.最小生成树的连接关系。(与当前帧有最大权重的最为该帧的父亲,该帧最为孩子)。
7 void UpdateBestCovisibles();
这个改变的是mvpOrderedConnectedKeyFrames,和mvOrderedWeights容器里面的值顺序,就是保证这里的值是从大到小排列的。
8 //得到与该关键帧有共视的关键帧set集合。
std::set<KeyFrame *> GetConnectedKeyFrames();
//得到与该关键帧有共视( 权重大于15)的关键帧的有序vector集合 std::vector<KeyFrame* > GetVectorCovisibleKeyFrames();
9 //返回 最好的共视向量集合 有<=N个关键帧
std::vector<KeyFrame*> GetBestCovisibilityKeyFrames(const int &N);
//返回的是大于该权重w的 所有共视关键帧 std::vector<KeyFrame*> GetCovisiblesByWeight(const int &w); //得到pKF与当前帧的权重 int GetWeight(KeyFrame* pKF);
10 // Spanning tree functions
void AddChild(KeyFrame* pKF);
void EraseChild(KeyFrame* pKF); void ChangeParent(KeyFrame* pKF); //得到最小生成树,该帧的所有孩子。 std::set<KeyFrame*> GetChilds(); KeyFrame* GetParent(); bool hasChild(KeyFrame* pKF);
跟最小生成树有关系,都很简单。
11 //可能检查到很多回环关键帧
void AddLoopEdge(KeyFrame* pKF);
//返回这些可能是回环的关键帧 std::set<KeyFrame*> GetLoopEdges();
改变的是公共变量spLoopEdges;值。
12// MapPoint observation functions 都是对vector<MapPoint* > mvpMapPoints做的操作。
//增加地图点, void AddMapPoint(MapPoint* pMP, const size_t &idx); void EraseMapPointMatch(const size_t &idx); void EraseMapPointMatch(MapPoint* pMP); void ReplaceMapPointMatch(const size_t &idx, MapPoint* pMP); //得到map point不是bad 的mappoint 集合 std::set<MapPoint*> GetMapPoints(); std::vector<MapPoint*> GetMapPointMatches(); //返回该关键帧里面,被跟踪的关键点的个数 int TrackedMapPoints(const int &minObs); MapPoint* GetMapPoint(const size_t &idx);
其他的函数也实现也十分简单,这里最后写下一个,很重要的函数。
13 void SetBadFlag();
该函数将该帧变成bad,mbToBeErased变成true,就是代表”删除了“。删除了该帧:
第一要改变该帧其连接帧的连接关系,删除该帧对地图点的额观测。第二改变最小生成树,改变最小生成树的具体实现:具体实现看代码。主要思路:
因为删除了当前帧,所有当前帧下面的孩子们(n个孩子)的父节点都要改变。我们就循环n次,重新为这n个孩子找父节点,父节点出现在与这些孩子节点有最多的共视权重的帧,并且在父节点候选容器(ParentCandidates)中里面的帧。选好了父亲点之后,把这个孩子节点加入剩下的孩子节点的父亲候选节点(sParentCandidates.insert(pC);),删除这个孩子节点( mspChildrens.erase(pC); )。