首页 > 其他分享 >ORB-SLAM ---- Frame::ComputeImageBounds和Frame::AssignFeaturesToGrid()

ORB-SLAM ---- Frame::ComputeImageBounds和Frame::AssignFeaturesToGrid()

时间:2024-10-14 12:52:06浏览次数:8  
标签:边界 AssignFeaturesToGrid Frame 网格 ---- imLeft 函数 mat

文章目录

一、Frame::ComputeImageBounds()

该函数的作用为计算函数边界,仅在第一帧或者标定参数变化后进行图像边界计算

1. 函数作用及讲解

在去畸变后,图像的边界会发生变化,图像不再是严格的边界,这个时候要找一个最小的矩形,恰好能将原来边界的四个顶点的包含进来

2. 源码及标注

void Frame::ComputeImageBounds(const cv::Mat &imLeft)
{
    // 如果畸变参数不为0,用OpenCV函数进行畸变矫正
    if(mDistCoef.at<float>(0)!=0.0)
    {
        // 保存矫正前的图像四个边界点坐标: (0,0) (cols,0) (0,rows) (cols,rows)
        cv::Mat mat(4,2,CV_32F);
        mat.at<float>(0,0)=0.0;             // 左上
        mat.at<float>(0,1)=0.0;
        mat.at<float>(1,0)=imLeft.cols;     // 右上
        mat.at<float>(1,1)=0.0;
        mat.at<float>(2,0)=0.0;             // 左下
        mat.at<float>(2,1)=imLeft.rows;
        mat.at<float>(3,0)=imLeft.cols;     // 右下
        mat.at<float>(3,1)=imLeft.rows;

        // Undistort corners
        // 将mat改为双通道(读取时一次读取两个成员,这里是x和y坐标)
        mat=mat.reshape(2);
        // 调用取畸变点函数
        // 第一二个参数为输入/输出的图像,第三个为相机内参,第四个为畸变系数,第五个为旋转矩阵R(这里表示无旋转),最后一个为新投影矩阵 
        cv::undistortPoints(mat,mat,mK,mDistCoef,cv::Mat(),mK);
        // 改回单通道
        mat=mat.reshape(1);
        // 去畸变后四个点围成的图形不再是严格的矩形,我们画一个最小能将四个点都装进去的矩形边界
        // 左边界取左上和左下的最小x坐标
        mnMinX = min(mat.at<float>(0,0),mat.at<float>(2,0));
        // 右边界取右上和右下的最大x坐标
        mnMaxX = max(mat.at<float>(1,0),mat.at<float>(3,0));
        // 上边界取左上和右上的最下y坐标
        mnMinY = min(mat.at<float>(0,1),mat.at<float>(1,1));
        // 下边界取左下和右下的最大y坐标
        mnMaxY = max(mat.at<float>(2,1),mat.at<float>(3,1));

    }
    else
    {
        // 如果没有畸变就取四个点为边界的四个顶点
        mnMinX = 0.0f;
        mnMaxX = imLeft.cols;
        mnMinY = 0.0f;
        mnMaxY = imLeft.rows;
    }
}

二、Frame::AssignFeaturesToGrid()

该函数的作用是将特征点分配到相应的网格中

1. 函数作用及讲解

先计算每个网格的预留容量,然后给他分配空间,最后用for循环的方式,将特征点分配到对应的网格内。对于前两步,有人会觉得多此一举,增加代码复杂度,但其实不是这样,这个步骤很重要,ORB-SLAM2之所以从众多视觉SLAM算法中脱颖而出,一个重要原因是他使用的空间小,计算速度快,代码中会出现很多这样的节省空间的操作,不积跬步,无以至千里。

2. 源码及标注

// 将特征点分配到网格中
void Frame::AssignFeaturesToGrid()
{
    // 计算每个网格块的容量,平均一个网格中有多少特征点
    // 这里乘以0.5的原因是,特征点分配不均匀,很多网格分配不到那么多特征点,所以乘以一个系数0.5,用来节省空间
    // 那么大于这个数量的网格会受到影响吗?答案是不会,因为我们用的容器是std::vector动态数组,如果分配空间不足的时候,户自动扩充
    int nReserve = 0.5f*N/(FRAME_GRID_COLS*FRAME_GRID_ROWS);
    
    // 遍历个网格与预留空间
    for(unsigned int i=0; i<FRAME_GRID_COLS;i++)
        for (unsigned int j=0; j<FRAME_GRID_ROWS;j++)
        // 给容器预留nReserve这么大的空间
            mGrid[i][j].reserve(nReserve);

    // 遍历每个特征点
    for(int i=0;i<N;i++)
    {
        // 将去畸变后的特征点信息存入kp中
        const cv::KeyPoint &kp = mvKeysUn[i];
        // 存储某个特征点所在网格的网格坐标,nGridPosX范围:[0,FRAME_GRID_COLS], nGridPosY范围:[0,FRAME_GRID_ROWS]
        int nGridPosX, nGridPosY;
        // 将每个特征点分到相应的网格中
        if(PosInGrid(kp,nGridPosX,nGridPosY))
            mGrid[nGridPosX][nGridPosY].push_back(i);
    }
}

3.调用的函数

Frame::AssignFeaturesToGrid()中调用了 Frame::PosInGrid()函数,该函数的作用是将特征点分配到网格类,剔除超出边界的特征点

// 确定特征点在网格中的位置,返回值为bool类型
bool Frame::PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY)
{
    // 计算特征点在哪个网格内
    posX = round((kp.pt.x-mnMinX)*mfGridElementWidthInv);
    posY = round((kp.pt.y-mnMinY)*mfGridElementHeightInv);

    //Keypoint's coordinates are undistorted, which could cause to go out of the image
    // 超出边界返回false
    if(posX<0 || posX>=FRAME_GRID_COLS || posY<0 || posY>=FRAME_GRID_ROWS)
        return false;
    // 可以正常分配返回true
    return true;
}

三、总结

在本篇博客写完后双目构造函数就全部结束了,还剩下一些在其他类中直接调用的函数,会在后续讲解,欢迎大家交流指正。

标签:边界,AssignFeaturesToGrid,Frame,网格,----,imLeft,函数,mat
From: https://blog.csdn.net/uzi_ccc/article/details/142908475

相关文章

  • 中小型企业网络的设计与实现
    资料下载中小型企业网络的设计与实现论文资源-CSDN文库 摘 要本文规划的是一个公司的网络搭建,网络设计包括了多个部门的网络架构,每个部门通过VLAN进行隔离,确保了网络的安全性和高效。华为企业网络模拟平台(ENSP)是一款针对华为企业网络产品设计的模拟软件。支持多种协议VL......
  • Spring Cloud 常用组件详解
    概述SpringCloud是一套微服务架构的开发工具,它为开发者提供了在分布式系统(尤其是微服务架构)中常见的那些模式的实现,例如服务发现、配置管理、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、决策竞选、分布式会话等等。这些模式都是围绕着微服务架构这一核心理念......
  • Android移动应用所需的工具
    基础配置Kotlin:Kotlin是一种兼具面向对象编程(OOPS)和函数式编程范式的静态类型现代编程语言。作为JVM语言,它与Java包和库完全兼容。由Google和JetBrains共同推出,Kotlin旨在成为Java的替代品,并已被Google指定为Android开发的官方语言。AndroidStudio:AndroidStudio是Android开发......
  • CAD软件:GstarCAD二次开发
    GstarCAD二次开发入门1.1二次开发概述GstarCAD是一款功能强大的CAD软件,广泛应用于建筑设计、机械制造、电子工程等领域。二次开发是指在现有的GstarCAD软件基础上,通过编程技术扩展其功能,满足特定的业务需求。二次开发可以大大提升工作效率,帮助用户解决复杂的设计问题。......
  • <<迷雾>> 第11章 全自动加法计算机(6)--一只开关取数 示例电路
    用一只开关依次将数取出info::操作说明刚启动时,t0=1,t1=t2=0,此时只有IAR`=1.按下开关K不要松开,地址寄存器AR收到一个上升沿信号,保存住当前地址,并提供给存储器(注:第一个地址为0,所以电路中暂看不出什么变化)松开开关K,循环移位计数器RR得到......
  • 初始C语言
    目录引语计算机语言的发展一.c语言的定义第一个c语言程序二.数据类型1.数据类型大小计算机单位换算......
  • Dynamsoft Barcode Reader SDK Java 10.4.2000
    ImprovingVendorManagementEfficiencywithOCRandDocumentProcessingEffectivevendormanagementintoday’sdynamicbusinesslandscapeofteninvolveshandlinglargevolumesofphysicaldocuments,whichposesasignificantchallenge.Extractingkeydeta......
  • ADS1292硬件电路调试总结
    作者:虚生一、前记ADS1292的硬件终于告一段落了。这期间遇到了不少问题,很多都是知识点层面的。最大的问题就是没有详细的了解芯片手册,在使用芯片之前还是应该仔细阅读芯片手册。如果需要ADS1299的芯片手册,可以和我联系。笔者在这里做个梳理。二、解析点重要引脚解析这里要......
  • 【华三】【华三】VXLAN典型组网-集中式网关配置实验
    【华三】VXLAN典型组网-二层组网静态配置实验VXLAN的相关术语VTEP(VXLANTunnelEndPoint)VXLAN隧道核心设备VSI(VirtualSwitchInstance)VSIinterfaceVXLANsegmentVNI(VXLANNetworkIdentifier)AC(AttachmentCircuit)VXLAN隧道工作模式L2Gateway:二层转发模式IPGateway:......
  • AutoDock 设置柔性残基时闪退
    目录问题解决方法解决步骤        1.卸载1.5.7版本的MGLTools        2.重新下载并安装1.5.6版本的MGLTools问题        AutoDock点击choosetorsionsincurrentlyselectedresidues后闪退解决方法        卸载1.5.7版本的MGLToo......