ROS-3DSLAM(十四)lvi-sam源代码阅读12 —— visual_loop阅读5

2021SC@SDUSC

(十四)lvi-sam源代码阅读12 —— visual_loop阅读5

visual_loop

loop_detection_node 1

继续上次的分析,回到loop_detection_node文件中,loopDetector将项目中预置的二进制字典集加载了进来并进行了初始化。

之后的部分,继续读取了另一个文件brief_pattern.yml,里面存储了若干个int数(暂时不知道干啥的)

// initialize brief extractor
string brief_pattern_file;
fsSettings["brief_pattern_file"] >> brief_pattern_file;  
brief_pattern_file = pkg_path + brief_pattern_file;
briefExtractor = BriefExtractor(brief_pattern_file);

brief_pattern.yml

%YAML:1.0
x1:
  - 0
  - 4
。。。
之后分别存储y1 x2 y2
共有254个(x1 x2 y1 y2)

根据文件名初步认为该文件与BRIEF描述子相关。

回到loop_detection_node,briefExtractor用该文件名进行了初始化,所以先分析以下BriefExtractor类。

parameters.h

BriefExtractor在parameters.h中定义

成员变量:

 DVision::BRIEF m_brief;

BRIEF类在上上次博客(https://blog.csdn.net/qq_38170211/article/details/121724849)中分析过,这里简单回顾一下:

该文件的作用是对于给定的图像和图像中的关键点,求出每个点的BRIEF描述子。

计算BRIEF描述子的方法是:对于每个关键点,取该关键点附近的若干组点对;对于每组点对中的点a,b,如果a>b,则为1;否则为0;最终计算得到一串01二进制串,就是该关键点的描述子(针对于某一特定选取的若干点对组:在文件中就是BRIEF.h里的x1,y1 x2,y2)

构造函数:

BriefExtractor(const std::string &pattern_file)
{
    // The DVision::BRIEF extractor computes a random pattern by default when
    // the object is created.
    // We load the pattern that we used to build the vocabulary, to make
    // the descriptors compatible with the predefined vocabulary
    //默认情况下,当创建对象时,DVision::BRIEF提取器会计算一个随机模式。我们加载用于构建词汇表的模式,以使描述符与预定义词汇表兼容
    // loads the pattern
    cv::FileStorage fs(pattern_file.c_str(), cv::FileStorage::READ);
    if(!fs.isOpened()) throw string("Could not open file ") + pattern_file;

    vector<int> x1, y1, x2, y2;
    fs["x1"] >> x1;
    fs["x2"] >> x2;
    fs["y1"] >> y1;
    fs["y2"] >> y2;

    m_brief.importPairs(x1, y1, x2, y2);
}

BRIEF.cpp

  inline void importPairs(const std::vector<int> &x1, 
    const std::vector<int> &y1, const std::vector<int> &x2, 
    const std::vector<int> &y2)
  {
    m_x1 = x1;
    m_y1 = y1;
    m_x2 = x2;
    m_y2 = y2;
    m_bit_length = x1.size();
  }

该函数的作用是:将一组特定的BRIEF描述子偏移点对组加载到BRIEF中,用于后续BRIEF描述子的计算;这里是将文件中预置的点对组加载进来。(后续通过函数BRIEF::compute计算描述子)

loop_detection_node 2

回到loop_detection_node后,下一条语句:

// initialize camera model
//camera model 需要分析
m_camera = camodocal::CameraFactory::instance()->generateCameraFromYamlFile(config_file.c_str());

camodocal::CameraFactory 在visual_feature/camera_models中定义。该部分是组内的罗源同学负责分析,但是还没有具体分析过这个类,所以这里我先简单的单独看一下这个函数,后续等同学分析完后再详细分析。

根据函数名称,初步推断这个语句的作用是通过yam文件初始化相机的相关参数。通过和舍友交流以及初步阅读了以下代码,应该能确定该函数的作用就是用来加载相机的相关参数,这些参数存储在文件params_camera.yml中。

CameraPtr
//参数:文件名称 params_camera.yml
CameraFactory::generateCameraFromYamlFile(const std::string& filename)
{
    //打开文件
    cv::FileStorage fs(filename, cv::FileStorage::READ);

    if (!fs.isOpened())
    {
        return CameraPtr();
    }

    Camera::ModelType modelType = Camera::MEI;
    //相机模型指的是相机坐标系到理想图像平面
    //读取文件中的model_type 这里用来判断相机的型号(根据params_camera.yml中可知本项目中的相机模型是MEI)
    if (!fs["model_type"].isNone())
    {
        std::string sModelType;
        fs["model_type"] >> sModelType;

        if (boost::iequals(sModelType, "kannala_brandt")) //鱼眼畸变模型
        {
            modelType = Camera::KANNALA_BRANDT;
        }
        else if (boost::iequals(sModelType, "mei")) //MEI model可以表示鱼眼和非鱼眼相机.
        {
            modelType = Camera::MEI;
        }
        else if (boost::iequals(sModelType, "scaramuzza")) //用任命命名的,暂时不知道是啥人名
        {
            modelType = Camera::SCARAMUZZA;
        }
        else if (boost::iequals(sModelType, "pinhole")) //针孔相机模型
        {
            modelType = Camera::PINHOLE;
        }
        else
        {
            std::cerr << "# ERROR: Unknown camera model: " << sModelType << std::endl;
            return CameraPtr();
        }
    }

    switch (modelType)
    {
    case Camera::KANNALA_BRANDT:
    {
        EquidistantCameraPtr camera(new EquidistantCamera);

        EquidistantCamera::Parameters params = camera->getParameters();
        params.readFromYamlFile(filename);
        camera->setParameters(params);
        return camera;
    }
    case Camera::PINHOLE:
    {
        PinholeCameraPtr camera(new PinholeCamera);

        PinholeCamera::Parameters params = camera->getParameters();
        params.readFromYamlFile(filename);
        camera->setParameters(params);
        return camera;
    }
    case Camera::SCARAMUZZA:
    {
        OCAMCameraPtr camera(new OCAMCamera);

        OCAMCamera::Parameters params = camera->getParameters();
        params.readFromYamlFile(filename);
        camera->setParameters(params);
        return camera;
    }
    case Camera::MEI: //项目中的相机模型(这里猜测应该是根据相机模型不同,要读取的参数也不同)
    default:
    {
        CataCameraPtr camera(new CataCamera);

        CataCamera::Parameters params = camera->getParameters();
        params.readFromYamlFile(filename);
        camera->setParameters(params);
        return camera;
    }
    }

    return CameraPtr();
}

VIO标定(二)广角相机模型 https://zhuanlan.zhihu.com/p/93822726 (介绍了一些列跟相机有关的模型,相机模型指的是相机坐标系到理想图像平面)

这样main函数里的初始化的部分基本完成,接下来就是分析几个订阅的话题以及发布的话题。接下来的分析以话题的回调函数展开(估计会分析不完了,会在课程结束后继续找时间分析)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值