slam标定(二) 双目立体视觉

2021-03-16 15:40:55 浏览数 (1)

视觉标定(二) 双目立体视觉标定

一、双目相机模型

 生活中,存在最多的就是单目相机,不过现在双摄,三摄手机基本取代了单目手机,我们先来说一下单目相机的缺点。单目相机在使用中存在尺度问题,先来看看下面这种图片。

 我们直接观察这副图片,是无法对图片中手掌上人的真实性进行判断,他们可能是一群很大但很远的人,也可能是一群很近且很小的模型,这种问题称之为尺度的不确定性。单目相机仅靠视觉无法消除尺度的不确定性,因此越来越多的人使用双目相机。

 上图为正在进行角点提取的双目鱼眼相机图片。双目相机由两个单目相机水平放置组成,两者之间的距离称为基线,通过基线,对像素空间远近进行判断,基本模拟了人眼的结构。我们先介绍双目相机的模型原理,最后进行双目相机的标定。

 如上所示,是左右相机中心,蓝线表示成像平面,为焦距,为双目相机基线,表示深度,即距离。空间点在左右相机中的成像点记作,为对应的像素坐标。由于相机基线的存在,空间点P在左右相机的成像点在理想情况下,应只有轴有偏移。根据三角形相似原理,我们可以得到下面关系式:

 化简可得:

 其中为视差,视觉与距离成反比,视察越大,距离越近,视察越小,距离越远。

二、双目标定原理

 从上一节可以看出,双目视觉是基于左右相机成像平面共面,且左右相机中心水平对齐才成立的。但现实中是因制造工艺,是不存在完全满足条件的双目相机,因为我们需要进行标定,对双目相机进行校正,目的就是将左右图像在水平方向进行严格的对齐,使得其对极线位于同一水平线,这样左右角点即可快速进行匹配。我们只要将左右相机的位姿关系,即旋转矩阵及平移矩阵标定出来即可。

 我们回忆一下上一期的内容,在上一期单目视觉标定当中,我们介绍了单应性矩阵,我们可以通过单应性矩阵得到棋盘格与相机之间的位姿关系。这里面有一个隐藏约束条件,即棋盘格平面是严格的平面关系,但双目标定我们是基于不共面条件作出推导计算,因此在这里我们不能通过单应性矩阵进行标定,下面我们介绍对极约束。

 上图为对极约束示意图,左右两个黑框表示左右两帧图像,分别表示两个相机的中心,即基线。空间点在左相机的投影为,在右相机的投影为,绿色平面称为对极平面,是投影在左平面的点,是投影在右平面的点,称为极点。与是对极平面与图像平面的交叉线,称之为对极线,同一相机的所有对极线相交于极点,同一对极平面的对极线一一对应。

 假设在左图中我们得到了一个点,我们不必在右图中进行全图搜索,对极约束把搜索空间压缩到了一条线上,大大缩短了计算量。下面我们进行对极约束的公式推导。

 记与分别为和,其表示的物理意义是空间点在左右相机坐标系中的坐标,基线即平移矩阵,记作,从左到右的变换为:

 因为旋转矩阵是正交矩阵,利用正交矩阵性质进行变换可得:

 利用共面三向量先作内积,再作外积等于0的性质,可得:

 带入整理可得:

 将按叉乘行列式展开计算,得到:

 其中表示反对称矩阵,即:

 再次带入,可得到:

 将再次带入,最终可得:

即Essential Matirx(本质矩阵),其仅仅与旋转矩阵、平移矩阵有关,如果将带入可得:

为Fundamental Matrix(基础矩阵),其不仅仅与位姿矩阵有关,还跟内参矩阵有关。

 因此,在双目标定中,我们首先标定出左右相机的内参与畸变参数,然后根据左右相机提取的角点按照极限约束进行对应角点的搜索匹配,计算基础矩阵,最后恢复出与。

三、标定步骤

 我们依然采用kalibr进行双目标定,在kalibr双目标定中,对极线搜索采用的是dijkstra算法,属于贪心算法,其不是我工作方向的重点,这里不给予详细介绍,感兴趣的朋友可以自行搜索学习。

 在标定板前晃动相机,采集2分钟左右的视频,双目图片如上所示,我使用的相机帧率是30Hz,然后通过一下命令行进行标定,相关命令及文件参数在上一期有所介绍,这里不再叙述。

代码语言:javascript复制
kalibr_calibrate_cameras --target 2april_6x6.yaml --bag someone.bag --models pinhole-equi pinhole-equi --topics /cam0/image_raw /cam1/image_raw

 在标定过程中,首先如上进行左右相机及各自内参畸变的初始化,然后按照极线约束,删除无效点,最后进行非线性优化,迭代提高精度,最终标定结果如下所示:

代码语言:javascript复制
cam0:
  cam_overlaps: [1]
  camera_model: pinhole
  distortion_coeffs: [-0.004409832074633388, -0.028437047407405637, 0.047809470007966905,
    -0.019523614941648112]
  distortion_model: equidistant
  intrinsics: [291.25351307096554, 291.4512970525461, 312.1777832831178, 207.2118864947473]
  resolution: [640, 400]
  rostopic: /cam0/image_raw
cam1:
  T_cn_cnm1:
  - [0.9999855873598229, -0.003937660912322113, 0.003649643705021668, -0.11901593055536226]
  - [0.003962421582737153, 0.9999690142275357, -0.0068021908246687045, -0.0026895627717159953]
  - [-0.003622745897063787, 0.006816554214125997, 0.9999702047065279, 0.001454727262296312]
  - [0.0, 0.0, 0.0, 1.0]
  cam_overlaps: [0]
  camera_model: pinhole
  distortion_coeffs: [0.0033687943075567796, -0.025984158273620172, 0.030334620264045077,
    -0.009876257637354948]
  distortion_model: equidistant
  intrinsics: [289.9578326809571, 289.88607463958084, 313.7645462282471, 206.31419561407202]
  resolution: [640, 400]
  rostopic: /cam1/image_raw

 可以看到基线结果为11.9cm,与我们的双目相机基线安装结果近似,我们认为标定结果正确。至此,双目相机标定完成,下一期我们介绍双目惯性(vio)系统的标定。

SLAM标定系列文章

1. slam标定(一) 单目视觉

2. IMU标定(三)确定误差的标定

3. IMU标定(二)随机误差的标定

4. IMU标定

Python高性能系列文章

  1. Python高性能计算之列表
  2. Python高性能计算之字典
  3. Python高性能计算之堆
  4. Python嵌套函数 闭包
  5. Python高性能计算之修饰符

6. 如何写出高性能的Python之修饰符functools.wraps

0 人点赞