视觉里程计--视觉slam7.1/相机运动估计视觉算法

2023-05-16

视觉里程计

本篇文章记录了少许阅读《视觉slam14讲》的阅读整理,不是特别全面,只是为了本次项目中特定任务搜查资料,时间比较紧,文章并没有全面涵盖所有知识点。日后若时间有空闲,将回来补充整理。

相机位姿估计

特征点法

首先,视觉里程计的核心问题是根据图像估计相机运动。利用特征点能够有效利用图像矩阵为我们提供的关于相机运动的信息。特征点一般具有可重复可区别高效率和本地性的特点。

特征点组成

关键点key-point描述子descriptor

关键点是指特征点的位置,描述子是按照相似的关键点一般具有相似的描述子设计的,如果2个特征点的描述子在向量空间上的距离相近,那么我们称他们是同样的特征点。

ORB特征

分为FAST关键点和BRIEF描述子

名称FAST关键点BRIEF描述子
原理比较像素点之间的亮度差异二进制高维度向量
优缺点速度快、重复性不强、分布不均匀
不具有尺度不变性以及方向性
速度快,有利于存储、适用于实时匹配
不具有旋转不变性
解决办法尺度:在不同层的图像金字塔匹配
方向性:计算图像灰度质心
旋转:关键点方向被计算出来的情况下可以计算旋转之后的Steer BRIEF

特征匹配

暴力匹配;浮点型关键点->匹配欧氏距离;二进制关键点->匹配汉明距离;特征点个数极多时,考虑快速近似最近邻FLANN算法。

特征点匹配核心代码(OpenCV)

//首先初始化部分、关键点、描述子、计算描述子指针、匹配matcher指针
//-- 初始化
    std::vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;
    Ptr<FeatureDetector> detector = ORB::create();
    Ptr<DescriptorExtractor> descriptor = ORB::create();
    // Ptr<FeatureDetector> detector = FeatureDetector::create(detector_name);
    // Ptr<DescriptorExtractor> descriptor = DescriptorExtractor::create(descriptor_name);
    Ptr<DescriptorMatcher> matcher  = DescriptorMatcher::create ( "BruteForce-Hamming" );
//之后
 //-- 第一步:检测 Oriented FAST 角点位置
    detector->detect ( img_1,keypoints_1 );
    detector->detect ( img_2,keypoints_2 );
//在之后,Mat存储描述子
 //-- 第二步:根据角点位置计算 BRIEF 描述子
    descriptor->compute ( img_1, keypoints_1, descriptors_1 );
    descriptor->compute ( img_2, keypoints_2, descriptors_2 );

可视化可以使用函数

drawKeypoints( img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
//最后是特征匹配
  //-- 第三步:对两幅图像中的BRIEF描述子进行匹配,使用 Hamming 距离
    vector<DMatch> matches;
    //BFMatcher matcher ( NORM_HAMMING );
    matcher->match ( descriptors_1, descriptors_2, matches );

关于DMatch这个类,可以理解为匹配关键点描述子的类,有以下成员,存着匹配对的各种信息,用于筛选匹配对

 DMatch.distance - 描述符之间的距离。越小越好。
• DMatch.trainIdx - 目标图像中描述符的索引。
• DMatch.queryIdx - 查询图像中描述符的索引。
• DMatch.imgIdx - 目标图像的索引

之后对匹配点对进行筛选

//-- 第四步:匹配点对筛选
    double min_dist=10000, max_dist=0;

    //找出所有匹配之间的最小距离和最大距离, 即是最相似的和最不相似的两组点之间的距离
    for ( int i = 0; i < descriptors_1.rows; i++ )
    {
        double dist = match[i].distance;
        if ( dist < min_dist ) min_dist = dist;
        if ( dist > max_dist ) max_dist = dist;
    }
//当描述子之间的距离大于两倍的最小距离时,即认为匹配有误.但有时候最小距离会非常小,设置一个经验值30作为下限.
    for ( int i = 0; i < descriptors_1.rows; i++ )
    {
        if ( match[i].distance <= max ( 2*min_dist, 30.0 ) )
        {
            matches.push_back ( match[i] );
        }
    }
}

以上代码中得到的

std::vector <cv::Dmatch> matches

即为最后获得筛选后的匹配对

之后顺便看到一个像素坐标系转相机坐标系的函数,顺便摘抄作为参考

Point2d pixel2cam ( const Point2d& p, const Mat& K )
{
    return Point2d
           (
               ( p.x - K.at<double> ( 0,2 ) ) / K.at<double> ( 0,0 ),
               ( p.y - K.at<double> ( 1,2 ) ) / K.at<double> ( 1,1 )
           );
}

翻译成公式就是
x c a m = x p x l − c x f x y c a m = y p x l − c y f y x_{cam} = \frac {x_{pxl} - {c_x}} {f_x} \\ y_{cam} = \frac {y_{pxl} - {c_y}}{f_y} xcam=fxxpxlcxycam=fyypxlcy

计算相机运动

已知情况采用方法效果
单目相机、两组2D点对极几何估计相机运动
双目相机、RGBD相机(两组3D点)ICP方法得到距离信息,估计相机运动
一组3D一组2DPnP求解估计相机运动

2D-2D

因为不太适用于本次比赛应用场景,先跳过这一步骤

三角测量

又称三角化,目的是求解目标特征点的空间位置,考虑两张不同视角的二维图,两图之间变换矩阵为T ,I1有特征点p1 , I2有特征点p2 , 都对应p点, 现在x1 x2是两个特征点的归一化坐标,已知R T,要求解两个特征点的深度s1 s2.

  1. 如果我们考虑计算s~1,首先我们有
    s 2 x 2 = s 1 R x 1 + t s_2x_2 = s_1Rx_1 + t s2x2=s1Rx1+t

  2. 对上式我们左乘 x 2 Λ x_2^{\Lambda} x2Λ

  3. s 2 x 2 Λ x 2 = 0 = s 1 x 2 Λ R x 1 + x 2 Λ t s_2x_2^{\Lambda}x_2 = 0 = s_1x_2^{\Lambda}Rx_1 + x_2^{\Lambda}t s2x2Λx2=0=s1x2ΛRx1+x2Λt

    可以解方程得到s2,有了s2之后s1也很易得

    注意,前提是对极几何中我们求解了相机位子,在此基础之上进行三角化求解特征点的空间位置,这是为了解决单目slam中的单幅图无法获取深度信息

//opencv中提供了封装的函数用于三角化
cv::triangulatePoints( T1, T2, pts_1, pts_2, pts_4d );

    // 转换成非齐次坐标
    for ( int i=0; i<pts_4d.cols; i++ )
    {
        Mat x = pts_4d.col(i);
        x /= x.at<float>(3,0); // 归一化
        Point3d p (
            x.at<float>(0,0), 
            x.at<float>(1,0), 
            x.at<float>(2,0) 
        );
        points.push_back( p );
    }//需要一步将其次坐标归一化并且转换为费其次坐标
//这函数的参数必须都是float类型的
Parameters:

projMatr1
3x4 projection matrix of the first camera.//左侧相机的RT矩阵(一般设置成eyes 0)
projMatr2
3x4 projection matrix of the second camera.//右侧相机的RT矩阵
projPoints1
2xN array of feature points in the first image. In case of c++ version it can be also a vector of feature points or two-channel matrix of size 1xN or Nx1.//左侧相机在相机坐标系下特征点坐标的集合
projPoints2
2xN array of corresponding points in the second image. In case of c++ version it can be also a vector of feature points or two-channel matrix of size 1xN or Nx1.//右侧相机在相机坐标系下特征点坐标的集合
points4D
4xN array of reconstructed points in homogeneous coordinates.//齐次坐标中的4xN

三角化测量中具有的深度不确定性可以根据深度滤波器来改进

3D-2D:PnP

终于来到了PnP,此方法描述了当知道n个3D空间点以及其投影位置时,估计相机的位姿。两张图像中的一张特征点的3D位置已知,最少需要3个点对以及至少1个额外点验证结果来估计相机运动,3D位置可以由三角化和RGBD相机的深度图确定,因此在双目或者rgbd相机的视觉里程计中

这里介绍很多PNP问题的求解方法,并且可以用非线性化的方式构造最小二乘问题迭代求解

直接线性变换DLT

已知一组3D点,以及他们在相机中的投影位置

可以求解给定地图和图像时的相机状态问题,如果把3D点看做另一个相机坐标系点的话,也可以求解两个相机的相对运动问题。

–后记–
关于相机运动估计,最后采取的解决办法实际上是跑一个slam的包,效果会比手写pnp来的更准,且操作也很方便。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

视觉里程计--视觉slam7.1/相机运动估计视觉算法 的相关文章

随机推荐

  • Linux:grep命令检索文件内容详解

    前言 Linux系统中搜索 查找文件中的内容 xff0c 一般最常用的是grep命令 xff0c 另外还有egrep命令 xff0c 同时vi命令也支持文件内容检索 下面来一起看看Linux利用grep命令检索文件内容的详细介绍 方法如下
  • stm32零基础应该怎么入门?

    单片机 xff08 microcontrollers xff09 是一种集成电路芯片 xff0c 是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU 多种I O口和中断系统 定时器 计数器等功能集成到一块硅片上构成的一个小而完善
  • Linux:CPU频率调节模式以及降频方法简介

    概述 cpufreq的核心功能 xff0c 是通过调整CPU的电压和频率 xff0c 来兼顾系统的性能和功耗 在不需要高性能时 xff0c 降低电压和频率 xff0c 以降低功耗 xff1b 在需要高性能时 xff0c 提高电压和频率 xf
  • Linux:rsyslog 日志丢失 messages lost due to rate-limiting

    系统日志显示 cat var log messages Apr 7 16 20 01 ngnodeb rsyslogd imjournal 154664 messages lost due to rate limiting 解决方法 修改配
  • Linux:shell 中的单行注释和多行注释

    关于 shell 中的单行注释和多行注释 单行注释 众所周知 xff0c 使用 比如想要注释 echo 34 Hello World 34 root 64 test vim test sh echo 34 Hello World 34 多行
  • Shell三剑客之sed:修改 xml

    修改前 vim config xml lt config input type verify 61 34 bool 34 name 61 34 flow bypass class 34 visible 61 34 true 34 gt fa
  • STM32串口通信

    STM32串口通信 一 基于寄存器与基于固件库编写的差异二 stm32串口通信实战1 烧录方式2 代码及效果图 三 C语言程序里全局变量 局部变量 堆 栈等概念四 stm32的堆 栈 全局变量的分配地址 一 基于寄存器与基于固件库编写的差异
  • keil下的FreeRtos多任务程序

    keil下的Freertos多任务程序 1 手动移植FreeRtos xff08 以STM32F103为例 xff09 2 直接使用野火的模板 1 手动移植FreeRtos xff08 以STM32F103为例 xff09 用该链接下载Fr
  • 随笔小记(二十七)

    神经网络中Epoch Iteration Batchsize相关理解和说明 batchsize xff1a 中文翻译为批大小 xff08 批尺寸 xff09 简单点说 xff0c 批量大小将决定我们一次训练的样本数目 batch size将
  • 手把手教物体检测——EfficientDet

    目录 摘要 训练数据 1 下载Pytoch版的EfficientDet 2 制作数据集 3 下载EfficientNets预训练模型 4 安装模型需要的包 5 放置数据集 6 修改train py中的参数 测试 注意 摘要 谷歌大脑团队 Q
  • 简化的围棋棋子规则(C++实现)

    题目 xff1a 输入棋盘 xff1a 1 1 2 3 2 3 3 3 2 3 3 3 2 2 2 3 3 3 1 2 2 2 3 3 2 1 1 2 3 1 其中1代表空 xff0c 2代表白子 xff0c 3代表黑子 xff09 输出
  • MATLAB中将图像转换为二值图像im2bw

    在MATLAB中将图像转换为二值图像 xff0c 主要运用im2bw函数 xff0c 涉及到一个灰度门槛的数值 对于灰度图像 bw 61 im2bw I level level空着的话 xff0c 默认是0 5 level一般使用grayt
  • Ubuntu 20.04 Gazebo安装 及模型库下载

    安装参考自官方教程noetic版本 xff0c 为了安装模型库 xff0c 就一起编辑了 1 设置你的电脑来接收软件 sudo sh c 39 echo 34 deb http packages osrfoundation org gaze
  • git pull强制覆盖本地修改

    有时本地代码做了修改 xff0c 但又想放弃这部分修改 xff0c 重新在新代码基础上进行开发 xff0c 这时可用如下方法覆盖先前修改 xff0c 并拉取远程仓更新本地代码 方法一 xff1a git fetch git reset ha
  • gazebo中视觉仿真怎么使用自定义贴图的问题

    gazebo中提供了很少的贴图 xff0c 场景只是用这几张贴图 xff0c 视觉SLAM仿真很容易在不该闭环的时候闭环 xff0c 导致根本没法用 那么我们怎么添加自己的贴图呢 xff1f 首先gazebo建模 使用默认贴图 xff0c
  • 传统定位方法简介--------里程计、IMU惯性传感器以及光电编码器等

    移动机器人最初是通过自身携带的内部传感器基于航迹推算的方法进行定位 xff0c 后来进一步发展到通过各种外部传感器对环境特征进行观测从而计算出移动机器人相对于整个环境的位姿 目前为止 xff0c 形成了基于多传感器信息融合的定位方法 现有移
  • 路由器接口

    深刻认识到如果不好好学习计算机网络 xff0c 对于自己学习后台的知识有很大的阻碍 所以 xff0c 这段时间好好把这方面的知识加强一下 一般路由器上的接口分为三大类 xff1a 一 用于局域网的LAN接口 二 用于广域网接入 互联的WAN
  • UART、I2C、SPI接口常见面试问题总结

    UART 定义 xff1a Universal Asynchronous Receiver Transmitter 通用异步收发传输器 特点 xff1a 速率不快 可全双工 结构上一般由波特率产生器 UART发送器 UART接收器组成 xf
  • ubuntu18.04配置ORB-SLAM3(包含ROS)完整版教程

    ORB SLAM3安装教程 ORB SLAM3安装准备1 C 43 43 11 or C 43 43 0x Compiler2 Pangolin 61 61 出现的问题 61 61 3 OpenCV安装4 Eigen安装5 boost安装6
  • 视觉里程计--视觉slam7.1/相机运动估计视觉算法

    视觉里程计 本篇文章记录了少许阅读 视觉slam14讲 的阅读整理 xff0c 不是特别全面 xff0c 只是为了本次项目中特定任务搜查资料 xff0c 时间比较紧 xff0c 文章并没有全面涵盖所有知识点 日后若时间有空闲 xff0c 将