• ORB-SLAM2 ---- ExtractorNode::DivideNode函数


    目录

    1.函数作用

    2.函数解析

    2.1 函数代码

    2.2 UR.x-UL.x这些变量怎么来的

    2.3 分裂节点代码解释 

    2.4  遍历当前提取器节点的vkeys中存储的特征点并分配给各个子节点


    1.函数作用

    ORB-SLAM2 ---- ORBextractor::DistributeOctTree函数_Courage2022的博客-CSDN博客

            将一个传进来的节点分裂成四个并恢复其特征点在节点中的分布。

    2.函数解析

    2.1 函数代码

    1. /**
    2. * @brief 将提取器节点分成4个子节点,同时也完成图像区域的划分、特征点归属的划分,以及相关标志位的置位
    3. *
    4. * @param[in & out] n1 提取器节点1:左上
    5. * @param[in & out] n2 提取器节点1:右上
    6. * @param[in & out] n3 提取器节点1:左下
    7. * @param[in & out] n4 提取器节点1:右下
    8. */
    9. void ExtractorNode::DivideNode(ExtractorNode &n1,
    10. ExtractorNode &n2,
    11. ExtractorNode &n3,
    12. ExtractorNode &n4)
    13. {
    14. //得到当前提取器节点所在图像区域的一半长宽,当然结果需要取整,step5 lit调用的这个函数当然就是当前节点的参数
    15. const int halfX = ceil(static_cast<float>(UR.x-UL.x)/2);
    16. const int halfY = ceil(static_cast<float>(BR.y-UL.y)/2);
    17. //Define boundaries of childs
    18. //下面的操作大同小异,将一个图像区域再细分成为四个小图像区块
    19. //n1 存储左上区域的边界
    20. n1.UL = UL;
    21. n1.UR = cv::Point2i(UL.x+halfX,UL.y);
    22. n1.BL = cv::Point2i(UL.x,UL.y+halfY);
    23. n1.BR = cv::Point2i(UL.x+halfX,UL.y+halfY);
    24. //用来存储在该节点对应的图像网格中提取出来的特征点的vector
    25. n1.vKeys.reserve(vKeys.size());
    26. //n2 存储右上区域的边界
    27. n2.UL = n1.UR;
    28. n2.UR = UR;
    29. n2.BL = n1.BR;
    30. n2.BR = cv::Point2i(UR.x,UL.y+halfY);
    31. n2.vKeys.reserve(vKeys.size());
    32. //n3 存储左下区域的边界
    33. n3.UL = n1.BL;
    34. n3.UR = n1.BR;
    35. n3.BL = BL;
    36. n3.BR = cv::Point2i(n1.BR.x,BL.y);
    37. n3.vKeys.reserve(vKeys.size());
    38. //n4 存储右下区域的边界
    39. n4.UL = n3.UR;
    40. n4.UR = n2.BR;
    41. n4.BL = n3.BR;
    42. n4.BR = BR;
    43. n4.vKeys.reserve(vKeys.size());
    44. //Associate points to childs
    45. //遍历当前提取器节点的vkeys中存储的特征点
    46. for(size_t i=0;isize();i++)
    47. {
    48. //获取这个特征点对象
    49. const cv::KeyPoint &kp = vKeys[i];
    50. //判断这个特征点在当前特征点提取器节点图像的哪个区域,更严格地说是属于那个子图像区块
    51. //然后就将这个特征点追加到那个特征点提取器节点的vkeys中
    52. //NOTICE BUG REVIEW 这里也是直接进行比较的,但是特征点的坐标是在“半径扩充图像”坐标系下的,而节点区域的坐标则是在“边缘扩充图像”坐标系下的
    53. if(kp.pt.x
    54. {
    55. if(kp.pt.y
    56. n1.vKeys.push_back(kp);
    57. else
    58. n3.vKeys.push_back(kp);
    59. }
    60. else if(kp.pt.y
    61. n2.vKeys.push_back(kp);
    62. else
    63. n4.vKeys.push_back(kp);
    64. }//遍历当前提取器节点的vkeys中存储的特征点
    65. //判断每个子特征点提取器节点所在的图像中特征点的数目(就是分配给子节点的特征点数目),然后做标记
    66. //这里判断是否数目等于1的目的是确定这个节点还能不能再向下进行分裂
    67. if(n1.vKeys.size()==1)
    68. n1.bNoMore = true;
    69. if(n2.vKeys.size()==1)
    70. n2.bNoMore = true;
    71. if(n3.vKeys.size()==1)
    72. n3.bNoMore = true;
    73. if(n4.vKeys.size()==1)
    74. n4.bNoMore = true;
    75. }

            我们的目的是将一个传进来的节点分裂成四个并恢复其特征点在节点中的分布。

    2.2 UR.x-UL.x这些变量怎么来的

            我们在ORBextractor::DistributeOctTree函数中,lit迭代器调用这个函数。

             即是对lit所指向的节点,而lit所指向节点的位置信息我们是在这里声明的。

    2.3 分裂节点代码解释 

    1. const int halfX = ceil(static_cast<float>(UR.x-UL.x)/2);
    2. const int halfY = ceil(static_cast<float>(BR.y-UL.y)/2);
    3. //Define boundaries of childs
    4. //下面的操作大同小异,将一个图像区域再细分成为四个小图像区块
    5. //n1 存储左上区域的边界
    6. n1.UL = UL;
    7. n1.UR = cv::Point2i(UL.x+halfX,UL.y);
    8. n1.BL = cv::Point2i(UL.x,UL.y+halfY);
    9. n1.BR = cv::Point2i(UL.x+halfX,UL.y+halfY);
    10. //用来存储在该节点对应的图像网格中提取出来的特征点的vector
    11. n1.vKeys.reserve(vKeys.size());
    12. //n2 存储右上区域的边界
    13. n2.UL = n1.UR;
    14. n2.UR = UR;
    15. n2.BL = n1.BR;
    16. n2.BR = cv::Point2i(UR.x,UL.y+halfY);
    17. n2.vKeys.reserve(vKeys.size());
    18. //n3 存储左下区域的边界
    19. n3.UL = n1.BL;
    20. n3.UR = n1.BR;
    21. n3.BL = BL;
    22. n3.BR = cv::Point2i(n1.BR.x,BL.y);
    23. n3.vKeys.reserve(vKeys.size());
    24. //n4 存储右下区域的边界
    25. n4.UL = n3.UR;
    26. n4.UR = n2.BR;
    27. n4.BL = n3.BR;
    28. n4.BR = BR;
    29. n4.vKeys.reserve(vKeys.size());

    2.4  遍历当前提取器节点的vkeys中存储的特征点并分配给各个子节点

    1. for(size_t i=0;isize();i++)
    2. {
    3. //获取这个特征点对象
    4. const cv::KeyPoint &kp = vKeys[i];
    5. //判断这个特征点在当前特征点提取器节点图像的哪个区域,更严格地说是属于那个子图像区块
    6. //然后就将这个特征点追加到那个特征点提取器节点的vkeys中
    7. //NOTICE BUG REVIEW 这里也是直接进行比较的,但是特征点的坐标是在“半径扩充图像”坐标系下的,而节点区域的坐标则是在“边缘扩充图像”坐标系下的
    8. if(kp.pt.x
    9. {
    10. if(kp.pt.y
    11. n1.vKeys.push_back(kp);
    12. else
    13. n3.vKeys.push_back(kp);
    14. }
    15. else if(kp.pt.y
    16. n2.vKeys.push_back(kp);
    17. else
    18. n4.vKeys.push_back(kp);
    19. }//遍历当前提取器节点的vkeys中存储的特征点

    2.5  判断节点是否可分裂

    1. if(n1.vKeys.size()==1)
    2. n1.bNoMore = true;
    3. if(n2.vKeys.size()==1)
    4. n2.bNoMore = true;
    5. if(n3.vKeys.size()==1)
    6. n3.bNoMore = true;
    7. if(n4.vKeys.size()==1)
    8. n4.bNoMore = true;

            如果节点中的特征点数目=1,置可分裂标志bNoMore 为-1。

  • 相关阅读:
    Leetcode171. Excel 表列序号
    《研发效能(DevOps)工程师(中级)认证》证书查询方式和路径丨IDCF
    qt指定窗体背景色以及各种颜色(生成调色方案)
    C# 上位机Modbus Crc校验方法
    Node 版本切换
    Matplotlib 绘制多图
    UEFI实战——显示进度条
    TreeMap的排序
    服务器数据恢复—OCFS2下raid5磁盘损坏导致阵列崩溃的数据恢复案例
    ES6中新增加的Map和Set数据结构的使用场景
  • 原文地址:https://blog.csdn.net/qq_41694024/article/details/126305067