SLAM十四讲之第5讲--相机标定

  • 1、相机模型
    • 1.1、针孔模型
    • 1.2、畸变模型
  • 2、标定
    • 2.1、旋转矩阵和平移向量
    • 2.2、棋盘
    • 2.3、各接口
      • 2.3.1、找到棋盘角点findChessboardCorners
      • 2.3.2、棋盘上的亚像素角点cornerSubPix()
      • 2.3.3、绘制棋盘角点drawChessboardCorners()
      • 2.3.4、calibrateCamera()标定函数
      • **2.3.5、solvePnP()计算外参数**
  • 3、标定结果评价

1、相机模型

  • 针孔模型
    相机将三维世界中的坐标点(单位为米)映射到二维图像平面(单位为像素)的过程能够用一个几何模型进行描述。这个模型有很多种,其中最简单的称为针孔模型。针孔模型是很常用而且有效的模型,它描述了一束光线通过针孔之后,在针孔背面投影成像的关系。

  • 畸变模型
    由于相机镜头上的透镜的存在,使得光线投影到成像平面的过程中会产生畸变。因此,我们使用针孔和畸变两个模型来描述整个投影过程。

1.1、针孔模型

此图是SLAM的

此图是OpenCV的

f是摄像机焦距,Z是相机到物体的距离,X是物体的长度,x图像平面上的物体图像。

以上涉及到相机的内参参数和外参参数。
1)内参: f x f_x fx​、 f y f_y fy​、 c x c_x cx​、 c y c_y cy​
2)外参: R R R、 t t t

1.2、畸变模型

为了获得好的成像效果,相机前方加了透镜。透镜的加人会对成像过程中光线的传播产生新的影响:
1)透镜自身的形状对光线传播的影响;
2)在机械组装过程中,透镜和成像平面不可能完全平行,这也会使光线穿过透镜投影到成像面时的位置发生变化。

  • 径向畸变
    由透镜形状引起的畸变(Distortion,也叫失真)称为径向畸变。它们主要分为两大类,桶形畸变和枕形畸变,如图5-3所示。

    对于径向畸变,成像光学中心的畸变为0,随着向边缘移动,畸变会变大。但实际上,这种畸变很小,用 r = 0 r=0 r=0附近的泰勒级数展开的前几项来描述。
    1)廉价网络相机,通常取前两项 k 1 , k 2 k_1, k_2 k1​,k2​
    2)畸变很大的相机,比如鱼眼透镜,加入第三个径向畸变项 k 3 k_3 k3​
    那么,成像装置上某点的径向位置可根据以下泰勒展示调整:
    { x d i s t o r t e d = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) y d i s t o r t e d = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) \begin{cases} x_{distorted} = x(1+k_1r^2+k_2r^4+k_3r^6) \\ y_{distorted} = y(1+k_1r^2+k_2r^4+k_3r^6) \end{cases} {xdistorted​=x(1+k1​r2+k2​r4+k3​r6)ydistorted​=y(1+k1​r2+k2​r4+k3​r6)​
    其中(x,y)是成像装置上畸变点的原始位置; ( x d i s t o r t e d , y d i s t o r t e d ) (x_{distorted},y_{distorted}) (xdistorted​,ydistorted​)是矫正后的新位置。

  • 切向畸变
    相机组装过程中,不能使透镜和成像平面平行,导致产生切向畸变。

    切向畸变可以用两个额外的参数 p 1 p_1 p1​和 p 2 p_2 p2​来表示;则:
    { x d i s t o r t e d = x + [ 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) ] y d i s t o r t e d = y + [ p 1 ( r 2 + 2 y 2 ) + 2 p 2 x y ] \begin{cases} x_{distorted} = x+[2p_1xy+p_2(r^2+2x^2)] \\ y_{distorted} = y+[p_1(r^2+2y^2)+2p_2xy] \end{cases} {xdistorted​=x+[2p1​xy+p2​(r2+2x2)]ydistorted​=y+[p1​(r2+2y2)+2p2​xy]​

将径向畸变和切向畸变统一到一起,得到矫正后的位置坐标:
{ x d i s t o r t e d = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + [ 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) ] y d i s t o r t e d = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) + [ p 1 ( r 2 + 2 y 2 ) + 2 p 2 x y ] \begin{cases} x_{distorted} = x(1+k_1r^2+k_2r^4+k_3r^6)+[2p_1xy+p_2(r^2+2x^2)] \\ y_{distorted} = y(1+k_1r^2+k_2r^4+k_3r^6)+[p_1(r^2+2y^2)+2p_2xy] \end{cases} {xdistorted​=x(1+k1​r2+k2​r4+k3​r6)+[2p1​xy+p2​(r2+2x2)]ydistorted​=y(1+k1​r2+k2​r4+k3​r6)+[p1​(r2+2y2)+2p2​xy]​

最后,通过相机内参,得到正确的位置坐标:

{ u = f x x d i s t o r t e d + c x v = f y y d i s t o r t e d + c y \begin{cases} u= f_xx_{distorted} + c_x\\ v= f_yy_{distorted} + c_y\end{cases} {u=fx​xdistorted​+cx​v=fy​ydistorted​+cy​​
以上畸变模型,涉及到的未知参数为: k 1 k_1 k1​、 k 2 k_2 k2​、 k 3 k_3 k3​、 p 1 p_1 p1​和 p 2 p_2 p2​

2、标定

对于第一部分未知的相机内参 f x f_x fx​、 f y f_y fy​、 c x c_x cx​、 c y c_y cy​和畸变内参 k 1 k_1 k1​、 k 2 k_2 k2​、 k 3 k_3 k3​、 p 1 p_1 p1​和 p 2 p_2 p2​;通过标定来实现对这些参数的计算。

  • 获取视频流frame,新增一个灰度值gray为frame的灰度数据;
  • 用gray找到棋盘角点findChessboardCorners;
  • (可选)棋盘格上的压像素点cornerSubPix();
  • 用frame绘制棋盘角点drawChessboardCorners();
  • 标定函数calibrateCamera();

2.1、旋转矩阵和平移向量

  • 三个角度 θ \theta θ、 ϕ \phi ϕ、 ψ \psi ψ表示三维旋转
  • 三个参数 x x x、 y y y、 z z z表示三维平移

相机内参 加上 旋转平移参数,对于每个视场,需要10个参数。每个视场固定8个参数因为不同视角下旋转和平移的6个参数会变化,对每一个视角用来求解摄像机内参数矩阵的两个额外参数需要约束。因此求解全部几何参数至少需要两个视角

2.2、棋盘

可以用作标定的标定板图案,有棋盘格、圆网格、随机图案、ArUco或者ChArUco图案。




2.3、各接口

2.3.1、找到棋盘角点findChessboardCorners


image:输入8bit灰度图数据
patternSize:棋盘每行和每列有多少角点,例如cv::Size(cols, rows),此值是内角点数,比如有8x8个 正方形格子,那么此处的内角点数为7*7
corners:这个接口的输出值,记录角点位置的输出矩阵,用像素坐标来表示角点位置的每个值。

2.3.2、棋盘上的亚像素角点cornerSubPix()

为了获得更准确的结果。

CV_EXPORTS_W void cornerSubPix( InputArray image, InputOutputArray corners,Size winSize, Size zeroZone,TermCriteria criteria );
  • image:8bit的灰度图数据
  • corners:作为输入,是findChessboardCorners接口的输出的结果;作为输出,是经过此亚像素定位接口,精确计算后的角点结果。
  • winSize:Half of the side length of the search window. For example, if winSize=Size(5,5) ,then a ( 5 ∗ 2 + 1 ) × ( 5 ∗ 2 + 1 ) = 11 × 11 (5*2+1) \times (5*2+1) = 11 \times 11 (5∗2+1)×(5∗2+1)=11×11 search window is used.
  • zeroZone:Half of the size of the dead region in the middle of the search zone over which the summation in the formula below is not done. It is used sometimes to avoid possible singularities of the autocorrelation matrix. The value of (-1,-1) indicates that there is no such a size.
  • criteria:Criteria for termination of the iterative process of corner refinement. That is,the process of corner position refinement stops either after criteria.maxCount iterations or when the corner position moves by less than criteria.epsilon on some iteration.

例子:

bool CalibProcessor::detectAndParseChessboard(const cv::Mat &frame)
{int chessBoardFlags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE | cv::CALIB_CB_FAST_CHECK;bool isTemplateFound = cv::findChessboardCorners(frame, mBoardSize, mCurrentImagePoints, chessBoardFlags);if (isTemplateFound) {cv::Mat viewGray;cv::cvtColor(frame, viewGray, cv::COLOR_BGR2GRAY);cv::cornerSubPix(viewGray, mCurrentImagePoints, cv::Size(11,11),cv::Size(-1,-1), cv::TermCriteria( cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 30, 0.1 ));cv::drawChessboardCorners(frame, mBoardSize, cv::Mat(mCurrentImagePoints), isTemplateFound);mTemplateLocations.insert(mTemplateLocations.begin(), mCurrentImagePoints[0]);}return isTemplateFound;
}

2.3.3、绘制棋盘角点drawChessboardCorners()

将findChessboardCorners()找到的角点绘制到彩色图像上。如果整个图案上的角点都找到,那么点将被绘制成不同的颜色(每一行都将有自己的颜色)。

image:8bit彩色图像数据
patternSize:参照findChessboardCorners()接口的说明
corners:findChessboardCorners接口的输出
patternWasFound:是否整个棋盘图案上的角点都被成功找到,findChessboardCorners返回值。

2.3.4、calibrateCamera()标定函数

这个接口可以得到相机内参矩阵,畸变系数、旋转向量和平移向量;最后返回一个double值,是标定结果的精度误差值(重投影误差)与projectPoints()方法结果一致【参见第三章节《3、标定结果评价》】。

  • objectPoints:向量的向量,每个向量包含特定图像的标定图案上的点得坐标。它是一个Nx3的矩阵,包含物体的每K个点在每M个图像上的物理坐标(即 N = K ∗ M N=K * M N=K∗M)。在使用棋盘格场合,定义坐标系使得所有棋盘上的点得 z z z坐标值为0,x和y坐标用其他单位度量。最简单的方式,定义棋盘的每个方块作为一个单位,假设 S w i d t h S_{width} Swidth​和 S h e i g h t S_{height} Sheight​分别为棋盘宽度和高度方向的方块个数;则
    ( x , y , z ) = ( 0 , 0 , 0 ) , ( 1 , 0 , 0 ) ( 2 , 0 , 0 ) , . . . ( 0 , 1 , 0 ) , ( 1 , 1 , 0 ) , . . . ( S w i d t h − 1 , S h e i g h t − 1 , 0 ) (x,y,z)=(0,0,0),(1,0,0)(2,0,0),...(0,1,0),(1,1,0),...(S_{width}-1,S_{height}-1,0) (x,y,z)=(0,0,0),(1,0,0)(2,0,0),...(0,1,0),(1,1,0),...(Swidth​−1,Sheight​−1,0)
    此为每个图像上的K个点得坐标。如果为M个图像,则继续push back即可。
  • imagePoints:向量的向量Nx2矩阵,包含每个图像中找到的每个点的位置。在棋盘格场合,此变量值由M次(即M个视图)调用findChessboardCorners()的返回值构成。push back(corners)
  • imageSize:原图像的大小
  • cameraMatrix:返回的相机内参矩阵
  • distCoeffs:返回畸变系数,可以是4,5或者8个元素。若长度为4,则畸变系数有 k 1 , k 2 , p 1 , p 2 k_1,k_2,p_1,p_2 k1​,k2​,p1​,p2​;若长度为5,则畸变系数比长度是4的多一个 k 3 k_3 k3​(此通常仅适用于鱼眼透镜);同理,若长度为8,则畸变系数多 k 4 , k 5 , k 6 k_4,k_5,k_6 k4​,k5​,k6​(场景:非常高精度的特殊透镜校准;且设置CALIB_RATIONAL_MODEL)。
  • rvecs:每个棋盘的旋转矩阵
  • tvecs:每个棋盘的平移矩阵

2.3.5、solvePnP()计算外参数

某种情况下,我们只知道了相机内参,需要单独计算相机外参(正在观察的对象的位置);此工作可以通过PnP问题进行求解,opencv给出了答案:

CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints,InputArray cameraMatrix, InputArray distCoeffs,OutputArray rvec, OutputArray tvec,bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE );
  • objectPoints
  • imagePoints
  • cameraMatrix
  • distCoeffs
  • rvec
  • tvec
  • useExtrinsicGuess
  • flags

3、标定结果评价

通过摄像机内外参数,对空间的三维点进行重新投影计算,得到空间三维点在图像上新的投影点的坐标,计算投影坐标和亚像素角点坐标之间的偏差。

CV_EXPORTS_W void projectPoints( InputArray objectPoints,InputArray rvec, InputArray tvec,InputArray cameraMatrix, InputArray distCoeffs,OutputArray imagePoints,OutputArray jacobian=noArray(),double aspectRatio=0 );
  • objectPoints:每个视图下标定图案上的点的坐标;即calibrateCamera()标定接口参数objectPoints的objectPoints[i];
  • rvec:标定接口calibrateCamera()计算出来的每张视图的旋转矩阵;
  • tvec:标定接口calibrateCamera()计算出来的每张视图的平移矩阵;
  • cameraMatrix:标定接口calibrateCamera()计算出来的内参矩阵;
  • distCoeffs:标定接口calibrateCamera()计算出来的畸变系数;
  • imagePoints:本投影接口计算得到的投影点坐标;
  • jacobian:(可选)jacobian matrix of derivatives of image points;
  • aspectRatio:(可选)“fixed aspect ratio” parameter. If the parameter is not 0, the function assumes that the aspect ratio f x / f y fx/fy fx/fy is fixed and correspondingly adjusts the jacobian matrix。

例子:

        vector<Point2f> imagePoints2;int i, totalPoints = 0;double totalErr = 0, err;for (int i ; i < (int)objectPointsList.size(); i++){projectPoints(Mat(objectPointsList[i]), rvecs[i],  tvecs[i],cameraMatrix, distCoeffs, imagePoints2);err = norm(Mat(imagePointsList[i]), Mat(imagePoints2), NORM_L2);int n = (int)objectPointsList[i].size();totalErr += err;totalPoints += n;}double error = std::sqrt(totalErr / totalPoints);cout << "error: " << error << endl;

SLAM十四讲之第5讲--相机标定相关推荐

  1. 视觉SLAM总结——视觉SLAM十四讲笔记整理

    视觉SLAM总结--视觉SLAM十四讲笔记整理 说明 基础知识点 1. 特征提取.特征匹配 (1)Harris (2)SIFT (3)SUFT (4)ORB (5)特征匹配 2. 2D-2D:对极约束 ...

  2. 浅读《视觉SLAM十四讲:从理论到实践》--操作1--初识SLAM

    浅读<视觉SLAM十四讲:从理论到实践>--操作1--初识SLAM 下载<视觉SLAM十四讲:从理论到实践>源码:https://github.com/gaoxiang12/s ...

  3. 视觉SLAM十四讲(3):三维空间刚体运动

    本章需要掌握的知识点有:旋转矩阵,变换矩阵,四元数,欧拉角定义和数学表达:同时也要掌握Eigen库关于矩阵.几何模块的使用方法. 文章目录 3.1 旋转矩阵 3.1.1 点,向量和矩阵的关系 3.1. ...

  4. 视觉SLAM十四讲(2):初识SLAM

    这一讲主要介绍视觉SLAM的结构,并完成第一个SLAM程序:HelloSLAM. 目录 2.1 小萝卜的例子 单目相机 双目相机 深度相机 2.2 经典视觉SLAM框架 2.3 SLAM问题的数学表述 ...

  5. 视觉SLAM十四讲(1):预备知识

    最近在学习高翔博士的<视觉SLAM十四讲>(第二版),算是初学本书,配套资源还算蛮丰富的,有代码(第一版和第二版都有),B站上也有高翔博士对第一版录制的讲解视频,真的是很贴心. 来吧,让我 ...

  6. 视觉slam十四讲 pdf_视觉SLAM十四讲|第12讲 回环检测

    1. 什么是回环检测 前面有说过累积误差的问题,前一时刻的误差会积累到后面,导致画不成圈圈,如图12-1所示,而画圈圈(全局一致性)很重要,所以需要有一个步骤来纠正当前的计算偏差. 回环检测通过判断相 ...

  7. 《SLAM十四讲》知识点梳理

    0.引言 SLAM十四讲把SLAM中涉及的基本知识点都涵盖了,知识梳理. 书本地址:http://www.broadview.com.cn/book/4938 书本代码:https://github. ...

  8. 视觉SLAM十四讲学习笔记-第七讲-视觉里程计-三角测量和实践

     专栏汇总 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第 ...

  9. 视觉SLAM十四讲学习笔记-第七讲-视觉里程计-对极几何和对极约束、本质矩阵、基础矩阵

    专栏系列文章如下:  专栏汇总 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-CSDN博客 视觉SLA ...

  10. 视觉SLAM十四讲学习笔记-第六讲学习笔记总结(1)---非线性优化原理

    第六讲学习笔记如下: 视觉SLAM十四讲学习笔记-第六讲-非线性优化的状态估计问题_goldqiu的博客-CSDN博客 ​​​​​​视觉SLAM十四讲学习笔记-第六讲-非线性优化的非线性最小二乘问题_ ...

最新文章

  1. Apache+PHP+MySQL+phpMyAdmin+WordPress搭建
  2. ANDROID 中设计模式的採用--创建型模式
  3. SQL group by底层原理——本质是排序,可以利用索引事先排好序
  4. 如何在Ubuntu18.04下安装CUDA10.1和cudnn
  5. 8除以2表示什么意思_八字中劫财,比肩分别表示什么意思
  6. 文件服务器 远程访问,远程访问文件服务器
  7. Windows 编程[8] - WM_PAINT 消息
  8. APP完整的启动流程
  9. 11月22日学习内容整理:bootstrap居中处理和组件,常用组件
  10. 总结 图(有向图、无向图、权、度、存储结构、邻接矩阵、领接表 概念)
  11. 磁力计的基本工作原理
  12. Vins-fusion gps融合 KITTY数据集测试
  13. Devexpress ASP.NET最新版开发.NET环境配置Visual Studo和SQL Server对应版本
  14. php左斜线和右斜线,左斜杠和右斜杠分别有什么意义?
  15. onnx-modifier:ONNX可视化编辑
  16. Linux如何安装FTDI D2XX驱动
  17. mysql删除重复记录语句
  18. c++计算数组的中值
  19. oracle中in与exists,Oracle中in和exists的区别
  20. ubuntu16.04下MERCURY无线网卡MW150UH问题解决

热门文章

  1. “5G+4G”聚合路由器多链路图传技术巩固安防监控行业
  2. Linux命令修改文件名和文件夹名
  3. Javascript对象相加
  4. 塞雷三分钟漫画中国史2
  5. python图像轮廓识别_Python+OpenCV图像处理(十六)—— 轮廓发现
  6. 似然函数、最大似然估计简单理解
  7. js中如何判断一个数是不是素数(三种方法)
  8. 网站访问速度加速的方法
  9. TreeMap、TreeSet简介
  10. Thread创建线程