当前位置: 首页 > news >正文

ORB-SLAM3的源码学习: Settings.cc:Settings::readCamera1/readCamera2 从配置文件中加载相机参数

前言

需要从配置文件yaml文件中读取相机参数才能用于后续计算。

1.函数声明

读取相机1的参数: 

void Settings::readCamera1(cv::FileStorage &fSettings)

如果是双目相机则还要读取相机2的参数:

void Settings::readCamera2(cv::FileStorage &fSettings)

2.函数定义 

相机1

1.读取相机模型

3的模型加入了针孔相机模型以及广角相机模型,可以利用模板函数读取参数,来确定相机的类型。

 bool found;

    // Read camera model
    string cameraModel = readParameter<string>(fSettings, "Camera.type", found);
2.如果是针孔相机模型

就进行如下操作:

读取相机参数构造相机模型,针对不同畸变参数的个数采用不同的方式进行读取,如果是单目相机和RGBD相机的话就需要进行去畸变操作。

vector<float> vCalibration;
    if (cameraModel == "PinHole")
    {
        cameraType_ = PinHole;//设置相机类型

        // Read intrinsic parameters读取内参
        float fx = readParameter<float>(fSettings, "Camera1.fx", found);
        float fy = readParameter<float>(fSettings, "Camera1.fy", found);
        float cx = readParameter<float>(fSettings, "Camera1.cx", found);
        float cy = readParameter<float>(fSettings, "Camera1.cy", found);

        vCalibration = {fx, fy, cx, cy};//储存在校准的变量中

        calibration1_ = new Pinhole(vCalibration);
        originalCalib1_ = new Pinhole(vCalibration);

        // Check if it is a distorted PinHole
        // 检查这个针孔相机的配置文件是否有畸变参数
        readParameter<float>(fSettings, "Camera1.k1", found, false);
        if (found)
        {
            readParameter<float>(fSettings, "Camera1.k3", found, false);
            if (found)
            {
                vPinHoleDistorsion1_.resize(5);//储存相机畸变参数的向量扩容。
                vPinHoleDistorsion1_[4] = readParameter<float>(fSettings, "Camera1.k3", found);
            }
            else
            {
                vPinHoleDistorsion1_.resize(4);
            }
            vPinHoleDistorsion1_[0] = readParameter<float>(fSettings, "Camera1.k1", found);
            vPinHoleDistorsion1_[1] = readParameter<float>(fSettings, "Camera1.k2", found);
            vPinHoleDistorsion1_[2] = readParameter<float>(fSettings, "Camera1.p1", found);
            vPinHoleDistorsion1_[3] = readParameter<float>(fSettings, "Camera1.p2", found);
        }

        // Check if we need to correct distortion from the images
        // 如果是单目相机或者是RGBD相机且有畸变参数则需要去畸变操作。
        if (
            (sensor_ == System::MONOCULAR ||
                sensor_ == System::IMU_MONOCULAR ||
                sensor_ == System::RGBD ||
                sensor_ == System::IMU_RGBD) &&
            vPinHoleDistorsion1_.size() != 0)
        {
            bNeedToUndistort_ = true;
        }
    }
 3.如果是矫正后的图像

此时认为是没有畸变的,就正常读取参数构造相机模型即可。

 //如果是校正后的图像则认为没畸变。
    else if (cameraModel == "Rectified")
    {
        cameraType_ = Rectified;

        // Read intrinsic parameters
        float fx = readParameter<float>(fSettings, "Camera1.fx", found);
        float fy = readParameter<float>(fSettings, "Camera1.fy", found);
        float cx = readParameter<float>(fSettings, "Camera1.cx", found);
        float cy = readParameter<float>(fSettings, "Camera1.cy", found);

        vCalibration = {fx, fy, cx, cy};

        calibration1_ = new Pinhole(vCalibration);
        originalCalib1_ = new Pinhole(vCalibration);

        // Rectified images are assumed to be ideal PinHole images (no distortion)
    }
4.如果是广角相机模型

需要在读取相机参数构建相机模型的基础上若是双目模式则要加上重叠区域参数读取以及构建重叠区域。

else if (cameraModel == "KannalaBrandt8")
    {
        cameraType_ = KannalaBrandt;

        // Read intrinsic parameters
        // 用模板函数读取yaml文件中的参数
        float fx = readParameter<float>(fSettings, "Camera1.fx", found);
        float fy = readParameter<float>(fSettings, "Camera1.fy", found);
        float cx = readParameter<float>(fSettings, "Camera1.cx", found);
        float cy = readParameter<float>(fSettings, "Camera1.cy", found);

        float k0 = readParameter<float>(fSettings, "Camera1.k1", found);
        float k1 = readParameter<float>(fSettings, "Camera1.k2", found);
        float k2 = readParameter<float>(fSettings, "Camera1.k3", found);
        float k3 = readParameter<float>(fSettings, "Camera1.k4", found);

        vCalibration = {fx, fy, cx, cy, k0, k1, k2, k3};

        calibration1_ = new KannalaBrandt8(vCalibration);
        originalCalib1_ = new KannalaBrandt8(vCalibration);
        //双目相机或IMU双目相机时,读取和设置摄像头的图像重叠区域参数。
        if (sensor_ == System::STEREO || sensor_ == System::IMU_STEREO)
        {
            int colBegin = readParameter<int>(fSettings, "Camera1.overlappingBegin", found);
            int colEnd = readParameter<int>(fSettings, "Camera1.overlappingEnd", found);
            vector<int> vOverlapping = {colBegin, colEnd};//摄像头重叠区域。

            static_cast<KannalaBrandt8 *>(calibration1_)->mvLappingArea = vOverlapping;
        }
    }
5.如果没有读取到相机模型

直接输出错误信息。

else
    {
        cerr << "Error: " << cameraModel << " not known" << endl;
        exit(-1);
    }

完整的代码 

void Settings::readCamera1(cv::FileStorage &fSettings)
{
    bool found;

    // Read camera model
    string cameraModel = readParameter<string>(fSettings, "Camera.type", found);

    vector<float> vCalibration;
    if (cameraModel == "PinHole")
    {
        cameraType_ = PinHole;//设置相机类型

        // Read intrinsic parameters读取内参
        float fx = readParameter<float>(fSettings, "Camera1.fx", found);
        float fy = readParameter<float>(fSettings, "Camera1.fy", found);
        float cx = readParameter<float>(fSettings, "Camera1.cx", found);
        float cy = readParameter<float>(fSettings, "Camera1.cy", found);

        vCalibration = {fx, fy, cx, cy};//储存在校准的变量中

        calibration1_ = new Pinhole(vCalibration);
        originalCalib1_ = new Pinhole(vCalibration);

        // Check if it is a distorted PinHole
        // 检查这个针孔相机的配置文件是否有畸变参数
        readParameter<float>(fSettings, "Camera1.k1", found, false);
        if (found)
        {
            readParameter<float>(fSettings, "Camera1.k3", found, false);
            if (found)
            {
                vPinHoleDistorsion1_.resize(5);//储存相机畸变参数的向量扩容。
                vPinHoleDistorsion1_[4] = readParameter<float>(fSettings, "Camera1.k3", found);
            }
            else
            {
                vPinHoleDistorsion1_.resize(4);
            }
            vPinHoleDistorsion1_[0] = readParameter<float>(fSettings, "Camera1.k1", found);
            vPinHoleDistorsion1_[1] = readParameter<float>(fSettings, "Camera1.k2", found);
            vPinHoleDistorsion1_[2] = readParameter<float>(fSettings, "Camera1.p1", found);
            vPinHoleDistorsion1_[3] = readParameter<float>(fSettings, "Camera1.p2", found);
        }

        // Check if we need to correct distortion from the images
        // 如果是单目相机或者是RGBD相机且有畸变参数则需要去畸变操作。
        if (
            (sensor_ == System::MONOCULAR ||
                sensor_ == System::IMU_MONOCULAR ||
                sensor_ == System::RGBD ||
                sensor_ == System::IMU_RGBD) &&
            vPinHoleDistorsion1_.size() != 0)
        {
            bNeedToUndistort_ = true;
        }
    }
    //如果是校正后的图像则认为没畸变。
    else if (cameraModel == "Rectified")
    {
        cameraType_ = Rectified;

        // Read intrinsic parameters
        float fx = readParameter<float>(fSettings, "Camera1.fx", found);
        float fy = readParameter<float>(fSettings, "Camera1.fy", found);
        float cx = readParameter<float>(fSettings, "Camera1.cx", found);
        float cy = readParameter<float>(fSettings, "Camera1.cy", found);

        vCalibration = {fx, fy, cx, cy};

        calibration1_ = new Pinhole(vCalibration);
        originalCalib1_ = new Pinhole(vCalibration);

        // Rectified images are assumed to be ideal PinHole images (no distortion)
    }
    else if (cameraModel == "KannalaBrandt8")
    {
        cameraType_ = KannalaBrandt;

        // Read intrinsic parameters
        // 用模板函数读取yaml文件中的参数
        float fx = readParameter<float>(fSettings, "Camera1.fx", found);
        float fy = readParameter<float>(fSettings, "Camera1.fy", found);
        float cx = readParameter<float>(fSettings, "Camera1.cx", found);
        float cy = readParameter<float>(fSettings, "Camera1.cy", found);

        float k0 = readParameter<float>(fSettings, "Camera1.k1", found);
        float k1 = readParameter<float>(fSettings, "Camera1.k2", found);
        float k2 = readParameter<float>(fSettings, "Camera1.k3", found);
        float k3 = readParameter<float>(fSettings, "Camera1.k4", found);

        vCalibration = {fx, fy, cx, cy, k0, k1, k2, k3};

        calibration1_ = new KannalaBrandt8(vCalibration);
        originalCalib1_ = new KannalaBrandt8(vCalibration);
        //双目相机或IMU双目相机时,读取和设置摄像头的图像重叠区域参数。
        if (sensor_ == System::STEREO || sensor_ == System::IMU_STEREO)
        {
            int colBegin = readParameter<int>(fSettings, "Camera1.overlappingBegin", found);
            int colEnd = readParameter<int>(fSettings, "Camera1.overlappingEnd", found);
            vector<int> vOverlapping = {colBegin, colEnd};//摄像头重叠区域。

            static_cast<KannalaBrandt8 *>(calibration1_)->mvLappingArea = vOverlapping;
        }
    }
    else
    {
        cerr << "Error: " << cameraModel << " not known" << endl;
        exit(-1);
    }
}

相机2

这时候已经默认是双目模式了,除了要进行相机1的操作,还要额外进行一些操作。

读取基线,计算基线焦距,读取深度。

// Load stereo extrinsic calibration
    if (cameraType_ == Rectified)
    {
        b_ = readParameter<float>(fSettings, "Stereo.b", found);
        bf_ = b_ * calibration1_->getParameter(0);
    }
    else
    {
        cv::Mat cvTlr = readParameter<cv::Mat>(fSettings, "Stereo.T_c1_c2", found);
        Tlr_ = Converter::toSophus(cvTlr);

        // TODO: also search for Trl and invert if necessary

        b_ = Tlr_.translation().norm();
        bf_ = b_ * calibration1_->getParameter(0);
    }

    thDepth_ = readParameter<float>(fSettings, "Stereo.ThDepth", found);

完整的代码 

void Settings::readCamera2(cv::FileStorage &fSettings)
{
    bool found;
    vector<float> vCalibration;
    if (cameraType_ == PinHole)
    {
        bNeedToRectify_ = true;

        // Read intrinsic parameters
        float fx = readParameter<float>(fSettings, "Camera2.fx", found);
        float fy = readParameter<float>(fSettings, "Camera2.fy", found);
        float cx = readParameter<float>(fSettings, "Camera2.cx", found);
        float cy = readParameter<float>(fSettings, "Camera2.cy", found);

        vCalibration = {fx, fy, cx, cy};

        calibration2_ = new Pinhole(vCalibration);
        originalCalib2_ = new Pinhole(vCalibration);

        // Check if it is a distorted PinHole
        readParameter<float>(fSettings, "Camera2.k1", found, false);
        if (found)
        {
            readParameter<float>(fSettings, "Camera2.k3", found, false);
            if (found)
            {
                vPinHoleDistorsion2_.resize(5);
                vPinHoleDistorsion2_[4] = readParameter<float>(fSettings, "Camera2.k3", found);
            }
            else
            {
                vPinHoleDistorsion2_.resize(4);
            }
            vPinHoleDistorsion2_[0] = readParameter<float>(fSettings, "Camera2.k1", found);
            vPinHoleDistorsion2_[1] = readParameter<float>(fSettings, "Camera2.k2", found);
            vPinHoleDistorsion2_[2] = readParameter<float>(fSettings, "Camera2.p1", found);
            vPinHoleDistorsion2_[3] = readParameter<float>(fSettings, "Camera2.p2", found);
        }
    }
    else if (cameraType_ == KannalaBrandt)
    {
        // Read intrinsic parameters
        float fx = readParameter<float>(fSettings, "Camera2.fx", found);
        float fy = readParameter<float>(fSettings, "Camera2.fy", found);
        float cx = readParameter<float>(fSettings, "Camera2.cx", found);
        float cy = readParameter<float>(fSettings, "Camera2.cy", found);

        float k0 = readParameter<float>(fSettings, "Camera1.k1", found);
        float k1 = readParameter<float>(fSettings, "Camera1.k2", found);
        float k2 = readParameter<float>(fSettings, "Camera1.k3", found);
        float k3 = readParameter<float>(fSettings, "Camera1.k4", found);

        vCalibration = {fx, fy, cx, cy, k0, k1, k2, k3};

        calibration2_ = new KannalaBrandt8(vCalibration);
        originalCalib2_ = new KannalaBrandt8(vCalibration);

        int colBegin = readParameter<int>(fSettings, "Camera2.overlappingBegin", found);
        int colEnd = readParameter<int>(fSettings, "Camera2.overlappingEnd", found);
        vector<int> vOverlapping = {colBegin, colEnd};

        static_cast<KannalaBrandt8 *>(calibration2_)->mvLappingArea = vOverlapping;
    }

    // Load stereo extrinsic calibration
    if (cameraType_ == Rectified)
    {
        b_ = readParameter<float>(fSettings, "Stereo.b", found);
        bf_ = b_ * calibration1_->getParameter(0);
    }
    else
    {
        cv::Mat cvTlr = readParameter<cv::Mat>(fSettings, "Stereo.T_c1_c2", found);
        Tlr_ = Converter::toSophus(cvTlr);

        // TODO: also search for Trl and invert if necessary

        b_ = Tlr_.translation().norm();
        bf_ = b_ * calibration1_->getParameter(0);
    }

    thDepth_ = readParameter<float>(fSettings, "Stereo.ThDepth", found);
}

结束语

以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。

相关文章:

  • 【信息学奥赛一本通 C++题解】1282:最大子矩阵
  • Linux 文件与目录命令学习记录
  • 语音识别中的MFCC特征提取:时频分析如何转化为机器可理解的声学参数?(附完整代码实现)
  • Python常见面试题的详解7
  • Python爬虫系列教程之第四篇:数据存储与管理
  • Kubernetes-node(节点) 组件
  • Java 包装类详解
  • 04运维实用篇(D4_日志)
  • Windows Server 中配置 Active Directory:从零到精通
  • Kubernetes 概述
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_cycle_t 类型
  • 数据库基本概念及基本使用
  • AcWing 801. 二进制中1的个数
  • kamailio常见问题解答
  • 1-16 tortoiseGit分支与Git操作
  • Windows逆向工程入门之栈指令与核心机制深度解析
  • 什么是原型?
  • Yolov5算法原理
  • 15.1 Process(进程)类
  • 基于 energy (lcl v3.0) 跨平台GUI框架实现的 XTA SDK GUI 源码实现
  • 西王食品连亏三年:主业齐“崩”,研发人员多为专科生
  • 波兰关闭俄罗斯驻克拉科夫领事馆
  • 2024年度全国秋粮收购达3.45亿吨
  • 金科股份重整方案通过,正式进入重整计划执行环节
  • 陈宝良 高寿仙 彭勇︱明清社会的皇权、商帮与市井百态
  • 中美经贸高层会谈在瑞士日内瓦开始举行