Kalibr源码学习(一): 重投影误差

2023-05-16

Kalibr源码学习(一): 重投影误差

给自己挖一个大坑, 从标定结果来学习Kalibr的标定源码, 这里基本以KB模型为例, 也就是标定时, kalibr的模型设定为 --model pinhole-equi , 这里以重投影误差开始,希望能坚持;

重投影误差标定结果

首先以重投影误差的txt文档的结果开始,
标定结果
可以看到上面的标定结果中, 重投影误差显示为 reprojection error: [-0.000002, -0.000000] +- [0.535272, 0.572115]
这里的两项对应的分别是 reprojection error: [x方向的重投影误差均值, y方向的重投影误差均值] +- [x方向重投影误差方差, y方向重投影误差方差]

其对应的代码片为:

//获取当前检测的角点,重投影坐标, 重投影误差
corners, reprojs, rerrs = getReprojectionErrors(cself, cidx) 
 if len(rerrs)>0:
 //获取重投影误差的均值me和方差se
 me, se = getReprojectionErrorStatistics(rerrs)
 //打印输出到txt文档中
 print >> dest, "\t reprojection error: [%f, %f] +- [%f, %f]" % (me[0], me[1], se[0], se[1])
 print >> dest

这里可以再说以下计算均值和方差的python代码:

在这里插入代码片
```def getReprojectionErrorStatistics(all_rerrs):
    #传入值是所有的误差 errors, 这里代码里面举出的例子usage是错误的,传入的应该是error,不是重投影
    if not len(all_rerrs)>0:
        raise RuntimeError("rerrs has invalid dimension")

    gc.disable() #append speed up
    rerr_matrix=list();
    for view_id, view_rerrs in enumerate(all_rerrs):
        if view_rerrs is not None: #if cam sees target in this view
            for rerr in view_rerrs:
                if not (rerr==np.array([None,None])).all(): #if corner was observed
                    rerr_matrix.append(rerr) #将误差值统一放入到rerr_matrix中
    rerr_matrix = np.array(rerr_matrix)
    gc.enable()
    
    mean = np.mean(rerr_matrix, 0, dtype=np.float)#计算均值
    std = np.std(rerr_matrix, 0, dtype=np.float)#计算方差
 
    return mean, std

重投影误差图像显示

重投影误差
这个图对应的代码为:

def plotAllReprojectionErrors(cself, cam_id, fno=1, noShow=False, clearFigure=True, title=""):
    # left: observations and projecitons
    # right: scatterplot of reprojection errors
    all_corners, reprojections, rerrs_xy = getReprojectionErrors(cself, cam_id)
    resolution = (cself.cameras[cam_id].geometry.projection().ru(), cself.cameras[cam_id].geometry.projection().rv())

    #创建图像
    values = np.arange(len(cself.views))/np.double(len(cself.views))
    cmap = pl.cm.jet(values,alpha=0.5)
    
    #子图一用来画重投影后的坐标 省略
    a=pl.subplot(121)

    #子图二用来画重投影误差
    sub = pl.subplot(122)
    for view_id, rerrs in enumerate(rerrs_xy):
        if rerrs is not None: #if this camerea sees the target in this view
            color = cmap[view_id,:]
            pl.plot(rerrs[:,0], rerrs[:,1], 'x', lw=3, mew=3, color=color)
   # 主要是这里,x代表的是重投影的x误差, y表示的是重投影的y值误差, 以 error_x 为横坐标, 以error_y为纵坐标,画图
    pl.axis('equal')
    pl.grid('on')
    pl.xlabel('error x (pix)')
    pl.ylabel('error y (pix)')

    #省略...

这里重点说一下获取重投影误差的函数, 经过层层调用, 最后计算出的其实是将三维点投影到图像上

//将传入的三维点投影到图像上
template<typename DISTORTION_T>
template<typename DERIVED_P, typename DERIVED_K>
bool PinholeProjection<DISTORTION_T>::euclideanToKeypoint(const Eigen::MatrixBase<DERIVED_P> & p,
    const Eigen::MatrixBase<DERIVED_K> & outKeypointConst) const {
  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE_OR_DYNAMIC(Eigen::MatrixBase<DERIVED_P>, 3);
  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE_OR_DYNAMIC(Eigen::MatrixBase<DERIVED_K>, 2);
  Eigen::MatrixBase<DERIVED_K> & outKeypoint = const_cast<Eigen::MatrixBase<DERIVED_K> &>(outKeypointConst);
   //shinan note: 转换到归一化相机平面 --> 加畸变 -->转换到像素平面
  outKeypoint.derived().resize(2);
  double rz = 1.0 / p[2];
  outKeypoint[0] = p[0] * rz;
  outKeypoint[1] = p[1] * rz;
   //加畸变
  _distortion.distort(outKeypoint);

  outKeypoint[0] = _fu * outKeypoint[0] + _cu;
  outKeypoint[1] = _fv * outKeypoint[1] + _cv;

  return isValid(outKeypoint) && p[2] > 0;
}

其中加畸变函数如下:

//将传入的归一化相机坐标系的三维点按照公式加畸变
template<typename DERIVED_Y>
void EquidistantDistortion::distort(const Eigen::MatrixBase<DERIVED_Y> & yconst) const {
  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE_OR_DYNAMIC(Eigen::MatrixBase<DERIVED_Y>, 2);
  Eigen::MatrixBase<DERIVED_Y> & y = const_cast<Eigen::MatrixBase<DERIVED_Y> &>(yconst);
  y.derived().resize(2);
  double r, theta, theta2, theta4, theta6, theta8, thetad, scaling;
  r = sqrt(y[0] * y[0] + y[1] * y[1]);
  theta = atan(r);
  theta2 = theta * theta;
  theta4 = theta2 * theta2;
  theta6 = theta4 * theta2;
  theta8 = theta4 * theta4;
  thetad = theta* (1 + _k1 * theta2 + _k2 * theta4 + _k3 * theta6 + _k4 * theta8);

  scaling = (r > 1e-8) ? thetad / r : 1.0;
  y[0] *= scaling;
  y[1] *= scaling;
}

总结

这里有一点就是这里的重投影误差的均值很小, 主要的原因可以从上面的彩色图中看出, 重投影误差有正有负,均值会出现互相抵消的状态; 总体来讲是以(-0.000002, -0.000000)为中心, 方差分别是0.535272, 0.572115的正态分布;

所以说,均值不可信,方差大概率更靠谱一些: 如下面标定的很好的结果中:
reprojection error: [0.000000, 0.000001] ± [0.115878, 0.107625]
方差仅为0.1, 其对应的重投影误差的值也都偏小:
重投影误差较小一点
根据3*sigma原则, 要想让大部分的重投影误差小于1个像素, 那么其所对应的方差应该是小于0.33.

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

Kalibr源码学习(一): 重投影误差 的相关文章

  • Kalibr联合标定相机—IMU总结(转载)

    转载自 xff1a https zhuanlan zhihu com p 47750214 Kalibr联合标定相机 IMU总结 李阳阳 公众号 码出名企路 xff0c 交流批评进步 Kalibr官网 ethz asl kalibr git
  • 联合标定双目相机和imu,使用工具Kalibr

    文章目录 imu标定 xff0c 产生数据写入imu yaml中 xff0c 见下文 xff0c imu yaml文件要用于联合标定 双目相机标定 xff0c 产生数据文件用于联合标定 xff0c 文件名类似camchain homeubu
  • Kalibr标定camera-IMU详细步骤

    Kalibr标定相机和IMU Camera IMU Calibration 基本情况 目的 我们进行camera IMU标定的目的是为了得到IMU和相机坐标系的相对位姿矩阵T和相对时间延时t shift t imu 61 t cam 43
  • intel Realsense D/T系列 kalibr标定

    kalibr官方源码GitHub ethz asl kalibr The Kalibr visual inertial calibration toolbox 鼠标下拉找到install follow the install wiki pa
  • 传感器标定系列——Kalibr工具

    文章目录 Kalibr介绍安装资源 Kalibr介绍 Kalibr is a toolbox that solves the following calibration problems 多相机标定 Multi Camera Calibra
  • VIO标定工具kalibr和imu_utils的使用

    0 参考资料 Kalibr进行IMU 43 相机的标定 xff1a 这个步骤写的非常好 xff0c 应该是目前看到的最符合的步骤了 使用ROS功能包标定相机内参 Kalibr标定camera IMU详细步骤 xff1a 这篇博客里给出了它的
  • Camera-IMU标定工具Kalibr的编译

    关于catkin make过程中下载suitesparse过久甚至失败的问题 xff1a 在安装kalibr时的suitesprse库时 xff0c 对应的cmakelists中会通过wget 下载压缩包 xff0c 若无法下载则整个kal
  • 学习Kalibr工具--Camera与IMU联合标定过程

    上一节介绍了 xff0c 用kalibr工具对camera进行标定的操作流程 xff0c 在camera标定之好之后 xff0c 进行camera与IMU进行联合标定的操作的学习 xff0c 即求取相机和IMU 之间的转换关系 坐标系之间的
  • Kalibr标定时卡在Extracting calibration target corners的问题

    问题 使用Kalibr标定单目相机与单目imu联合标定 xff0c 都出现卡在Extracting calibration target corners的问题 xff0c 因此做一个记录 运行标定命令后一直卡在下面 Initializing
  • 利用Kalibr标定双目相机与IMU

    本文介绍如何利用Kalibr标定工具进行双目相机与IMU的联合标定 主要过程包括以下四步 xff1a 生成标定板标定双目相机标定IMU联合标定 1 生成标定板 使用AprilTag rosrun kalibr kalibr create t
  • 安装kalibr踩坑1:Could NOT find GTest (missing: GTEST_LIBRARY GTEST_MAIN_LIBRARY)

    Could NOT find GTest missing GTEST LIBRARY GTEST MAIN LIBRARY 因为GTest虽然安装过 xff0c 但是好像找不到头文件 sudo apt get install libgtes
  • Kalibr标定d435i

    figure it out 最近准备使用realsense d435i xff0c 先对其进行标定 整体环境是基于ROS的 xff0c 因为Kalibr是在ROS环境下 大致过程如下 xff1a imu标定 gt 双目标定 gt 双目 43
  • bmi055 标定_Kalibr tutorials

    Kalibr installation tutorial I was confused about installing Kalibr but there is no even one hint in README md I just pu
  • 联合标定单目相机和imu,使用工具Kalibr

    使用Kalibr工具标定单目相机和IMU的外参 xff0c 操作过程和联合标定双目相机和IMU类似 xff0c 以下介绍不同部分 最后标定时所需要的相机参数由双目变成了单目 xff0c 以下是配置文件的格式 xff1a cam0 camer
  • 《深入剖析tomcat》读书笔记3--servlet容器

    主要是 深入剖析tomcat 的第五章和第十一章 个人觉得如下3点是关键 1 pipeline相关概念及其执行valve的顺序 2 standardwrapper的接受http请求时候的调用序列 3 standardwrapper基础阀加载
  • SpringBoot自动装配原理

    文章目录 一 简介 二 自动装配源码分析 三 自动装配以mybatis举例 四 总结 一 简介 Spring Boot 的自动装配 Auto configuration 是 Spring Boot 框架中一项强大的功能 它可以根据应用程序的
  • 【Spring Boot 源码学习】@SpringBootApplication 注解

    Spring Boot 源码学习系列 SpringBootApplication 注解 引言 主要内容 1 创建 Spring Boot 项目 2 Spring Boot 入口类 3 SpringBootApplication 介绍 总结
  • 5种很牛的两位数乘法速算方法

    5种很牛的两位数乘法速算方法 第一种 十几乘以任意两位数 公式推导 10 b 10c d 100c 10 bc d bd 10 10c bc d bd 10 10c d bc bd 方法 如果c 1 公式是 10 b 10 d 10 10
  • 10秒钟脱口而出十位数相同两位数的乘法

    10秒钟脱口而出十位数相同两位数的乘法 一 范围 十位数相同的两位数 二 目标 计算两位数的相乘 10秒钟脱口而出 三 基本公式 以尾数之和展开讨论 假设两个数分别是10a b以及10a c 那么尾数之和就是b c 序号 分类 公式 举例
  • 【Spring Boot 源码学习】OnClassCondition 详解

    Spring Boot 源码学习系列 OnClassCondition 详解 引言 往期内容 主要内容 1 getOutcomes 方法 2 多处理器拆分处理 3 StandardOutcomesResolver 内部类 4 getMatc

随机推荐

  • Ubuntu18.04安装Nvidia显卡驱动,CUDA+CUDNN,完整Qt,编译安装OpenCV4.1.1 with CUDA and Qt

    目录 N卡无法开机问题一 安装Nvidia显卡驱动1 禁用安全引导2 禁用默认驱动程序3 添加Nvidia驱动源4 安装驱动 二 安装CUDA和CUDNN1 下载2 安装3 配置环境变量4 测试CUDA5 下载 xff0c 安装CUDNN
  • 纯C语言实现仿C++STL泛型链表

    声明 本代码完全开源 xff0c 可以用于任意用途 xff0c 但代码并未做完善的测试 xff0c 性能也不能保障 xff0c 主要用于初学者学习 源码链接 xff1a GitHub 一 原理 普通的单向链表的原理就是一个节点存储着数据和指
  • Ubuntu上使用CLion开发STM32,并使用JLink下载、调试

    目录 一 环境准备二 下载STM32CubeMX固件库三 使用STM32CubeMX创建工程四 CLion配置五 CMake简单操作和添加DSP库CMake简单操作添加DSP库 五 调试时查看外设寄存器 六 使用JLinkGDBServer
  • C++进阶——STL源码之迭代器(iterators)

    STL迭代器 在 STL 编程中 xff0c 容器和算法是独立设计的 xff0c 即数据结构和算法是独立设计的 xff0c 连接容器和算法的桥梁就是迭代器了 xff1a 迭代器是一种行为类似指针的对象 xff0c 而指针的各种行为中最常见也
  • C++基础——STL常见问题总结

    1 STL由哪些组件组成 容器 xff08 Containers xff09 xff1a 各种数据结构 xff0c 如 xff1a vector list deque set map 用来存放数据 从实现的角度来看 xff0c STL容器是
  • private static final long serialVersionUID = 1L 干什么的?

    private static final long serialVersionUID 61 1L xff1b 是定义以一个序列号 java源码里有大量的类都有这么一个序列号 目的就是把java对象序列化而后进行保存 java的序列化机制式通
  • 协议:PELCO-D

    PELCO D的功能是用于矩阵和其它设备之间的通信协议 基本信息 数据格式 xff1a 1位起始位 8位数据 1位停止位 xff0c 无校验位 波特率 xff1a 2400B S 命令格式 字节1 字节2 字节3 字节4 字节5 字节6 字
  • 9年FPGA工作经验,转行了,苦海无涯……

    整理 xff1a 付斌 xff0c 内容来自网络 01 9年峥嵘岁月 我很少说话 xff0c 因为怕被人鄙视 工作了9年的fpga xff0c 总要总结 其实说我的fpga经验 xff0c 也是一坨屎 三年的 xff0c 用altera的c
  • GPS-RTK

    一点一点的补充吧 背景 1 xff0e 各种控制测量传统的大地测量 工程控制测量采用三角网 导线网方法来施测 xff0c 不仅费工费时 xff0c 要求点间RTK 在工程测量的应用通视 xff0c 而且精度分布不均匀 xff0c 且在外业不
  • 浅谈栈帧

    一 什么是栈帧 xff1f 什么是栈帧 xff0c 首先引用百度百科的经典解释 xff1a 栈帧也叫过程活动记录 xff0c 是编译器用来实现过程 函数调用的一种数据结构 实际上 xff0c 可以简单理解为 xff1a 栈帧就是存储在用户栈
  • madVR+potplay 基本设置

    ctrl 43 j 调出 madvr 的OSD菜单 如下图 xff1a 如何设置 madVR 10bit 输出 xff1a 1 确保视频源是10bit 源 2 显示器设置 如下 xff1a 3 渲染设置如下 xff1a 设置完成 xff0c
  • 4.jetson更换python版本

    问题与背景 jetson自带的python版本是3 6 9 xff0c 太老旧了 xff0c 希望更换python版本 尝试替换成python3 7的版本 但是在未替换之前 xff0c 已经装了pip3了 xff0c 是否pip3会与pyt
  • char数组和指针的区别

    一个简单的字符分割函数引发的思考 char SegStr1 const char pSrc int n int nLen 61 strlen pSrc char ptrSrc 256 61 0 char pSeg 61 ptrSrc for
  • 舒尔补理论Schur Compliment

    在做slam的时候经常遇到的一个概念就是schur complement xff0c 了解这个概念 xff0c 对于理解slam的优化过程也会有很大的帮助 xff1b 首先给出的是舒尔补的定义 xff1a 舒尔补的由来其实就是将一个矩阵变成
  • 用CubeSLAM跑自己的数据集

    针对CubeSLAM本博客内容如下 xff0c 主要是阅读论文和代码的一些结果总结 xff0c 还有一部分总结未完成 xff0c 同样使用或者对语义slam感兴趣有经验的欢迎交流 xff0c 该博客后面也会不段更新cubeslam在自己的数
  • mipi接口的摄像头驱动并发布话题

    情况 需要跑ORBSLAM 之前一直使用USB接口的相机 打开摄像头一般使用的是ROS下的usb cam node进行驱动 采集图像并发布成topic的形式 或者使用opencv的videoCapture进行图像的捕捉 因为某些原因需要将u
  • 正确使用StereoRectify

    双目矫正的使用 cv fisheye StereoRectify 函数 主要用于对双目图像做出矫正 计算出用于立体矫正的参数 具体的使用方法如下 void cv fisheye stereoRectify InputArray K1 Inp
  • Eigen问题解决:eigen_assert_exception’ is not a member of ‘Eigen’

    很意外地遇到一个Eigen相关的错误 xff1a usr local include eigen3 Eigen src Core products Parallelizer h 162 40 error eigen assert excep
  • 2020年大学生电子设计竞赛,又来了!

    不知不觉 xff0c 又临近5月份 xff0c 疫情下的各个比赛活动都受到了影响 xff0c 今年是偶数年 xff0c 暑期应该是各个省份的电子设计竞赛比赛之时 还有三四个月 xff0c 有想参加的比赛的同学应该可以提前准备了 关于比赛的帖
  • Kalibr源码学习(一): 重投影误差

    Kalibr源码学习 一 重投影误差 给自己挖一个大坑 从标定结果来学习Kalibr的标定源码 这里基本以KB模型为例 也就是标定时 kalibr的模型设定为 model pinhole equi 这里以重投影误差开始 希望能坚持 重投影误