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