目录

  • 1 相机为什么要标定?
  • 2 反解相机矩阵
  • 3 反解畸变系数
  • 4 去畸变原理与实战

1 相机为什么要标定?

直接给结论:相机标定的目的是为了获得相机矩阵和畸变系数。这部分内容可以参考计算机视觉教程0-3:为何拍照会有死亡视角?详解相机矩阵与畸变。获得了相机矩阵和畸变系数后就能进行更高级的应用,主要应用于立体视觉领域,例如视觉SLAM、三维导航、双目测距等,总之,相机标定相当重要。

相机标定的经典方法是张正友标定法,需要下面的张正友标定板。本节将详细地从底层数学原理推导张正友标定法。

2 反解相机矩阵

不考虑畸变,对图像中标定板角点进行检测,得到角点像素坐标值[uv1]T\left[ \begin{matrix} u& v& 1\\\end{matrix} \right] ^T[u​v​1​]T,根据已知棋盘格大小,计算世界坐标系下标定板角点的世界坐标值[W⁣⁣XW⁣⁣ ⁣  ⁣ YW⁣⁣Z1]T\left[ \begin{matrix} ^{\boldsymbol{W}\!}\!X& ^{\boldsymbol{W}\!}\!\!\:\!\:Y& ^{\boldsymbol{W}\!}\!Z& 1\\\end{matrix} \right] ^T[WX​WY​WZ​1​]T,此时从世界坐标到像素坐标的映射为

[u^v^1]=K[WC⁣ ⁣ ⁣RC⁣pw0][W⁣⁣XW⁣⁣ ⁣  ⁣ YW⁣⁣Z1]\left[ \begin{array}{c} \hat{u}\\ \hat{v}\\ 1\\\end{array} \right] =\boldsymbol{K}\left[ \begin{matrix} _{\boldsymbol{W}}^{\boldsymbol{C}}\;\!\!\!\boldsymbol{R}& ^{\boldsymbol{C}}\!\boldsymbol{p}_{w_0}\\\end{matrix} \right] \left[ \begin{array}{c} ^{\boldsymbol{W}\!}\!X\\ ^{\boldsymbol{W}\!}\!\!\:\!\:Y\\ ^{\boldsymbol{W}\!}\!Z\\ 1\\\end{array} \right]⎣⎡​u^v^1​⎦⎤​=K[WC​R​Cpw0​​​]⎣⎢⎢⎡​WXWYWZ1​⎦⎥⎥⎤​

通常将世界坐标系与标定板固连使W⁣⁣Z=0^{\boldsymbol{W}\!}\!Z=0WZ=0,如图所示

此时映射关系简化为

[u^v^1]=K[r1r2p][W⁣⁣XW⁣⁣ ⁣  ⁣ Y1]\left[ \begin{array}{c} \hat{u}\\ \hat{v}\\ 1\\\end{array} \right] =\boldsymbol{K}\left[ \begin{matrix} \boldsymbol{r}_1& \boldsymbol{r}_2& \boldsymbol{p}\\\end{matrix} \right] \left[ \begin{array}{c} ^{\boldsymbol{W}\!}\!X\\ ^{\boldsymbol{W}\!}\!\!\:\!\:Y\\ 1\\\end{array} \right]⎣⎡​u^v^1​⎦⎤​=K[r1​​r2​​p​]⎣⎡​WXWY1​⎦⎤​

其中r1\boldsymbol{r}_1r1​、r2\boldsymbol{r}_2r2​是旋转矩阵WC⁣ ⁣ ⁣R_{\boldsymbol{W}}^{\boldsymbol{C}}\;\!\!\!\boldsymbol{R}WC​R的前两列。

设从标定板到成像平面的单应性矩阵为

H=[h11h12h13h21h22h23h31h32h33]=[h1h2h3]\boldsymbol{H}=\left[ \begin{matrix} h_{11}& h_{12}& h_{13}\\ h_{21}& h_{22}& h_{23}\\ h_{31}& h_{32}& h_{33}\\\end{matrix} \right] =\left[ \begin{matrix} \boldsymbol{h}_1& \boldsymbol{h}_2& \boldsymbol{h}_3\\\end{matrix} \right]H=⎣⎡​h11​h21​h31​​h12​h22​h32​​h13​h23​h33​​⎦⎤​=[h1​​h2​​h3​​]

这部分内容可以参考计算机视觉教程1-2:单应性矩阵估计

下面基于已知的H\boldsymbol{H}H反解内参矩阵K\boldsymbol{K}K,代入hi=Kri(i=1,2)\boldsymbol{h}_i=\boldsymbol{Kr}_i\left( i=1,2 \right)hi​=Kri​(i=1,2)可得

{h1TQh2=0h1TQh1=h2TQh2=1\begin{cases} \boldsymbol{h}_{1}^{T}\boldsymbol{Qh}_2=0\\ \boldsymbol{h}_{1}^{T}\boldsymbol{Qh}_1=\boldsymbol{h}_{2}^{T}\boldsymbol{Qh}_2=1\\\end{cases}{h1T​Qh2​=0h1T​Qh1​=h2T​Qh2​=1​

其中对称矩阵Q=K−TK−1\boldsymbol{Q}=\boldsymbol{K}^{-T}\boldsymbol{K}^{-1}Q=K−TK−1

考虑到

hiTQhj=[hi1hi2hi3][q1q2q3q2q4q5q3q5q6][hj1hj2hj3]=vijTq\boldsymbol{h}_{i}^{T}\boldsymbol{Qh}_j=\left[ \begin{matrix} h_{i1}& h_{i2}& h_{i3}\\\end{matrix} \right] \left[ \begin{matrix} q_1& q_2& q_3\\ q_2& q_4& q_5\\ q_3& q_5& q_6\\\end{matrix} \right] \left[ \begin{array}{c} h_{j1}\\ h_{j2}\\ h_{j3}\\\end{array} \right] \\=\boldsymbol{v}_{ij}^{T}\boldsymbol{q}hiT​Qhj​=[hi1​​hi2​​hi3​​]⎣⎡​q1​q2​q3​​q2​q4​q5​​q3​q5​q6​​⎦⎤​⎣⎡​hj1​hj2​hj3​​⎦⎤​=vijT​q

可以改写为

[v12Tv11T−v22T]q=0\left[ \begin{array}{c} \boldsymbol{v}_{12}^{T}\\ \boldsymbol{v}_{11}^{T}-\boldsymbol{v}_{22}^{T}\\\end{array} \right] \boldsymbol{q}=0[v12T​v11T​−v22T​​]q=0

其中矩阵V\boldsymbol{V}V完全由已知的H\boldsymbol{H}H导出,q\boldsymbol{q}q为Q\boldsymbol{Q}Q的向量形式。由于一个H\boldsymbol{H}H最多只能贡献两个线性方程,因此确定内参矩阵至少要3张标定板(工程上一般取15~20张为宜),这些方程共同构成Vq=0\boldsymbol{Vq}=0Vq=0,可用计算机视觉教程1-2:单应性矩阵估计的基本DLT算法解算,解出来就是相机内参矩阵。

3 反解畸变系数

张氏标定法仅考虑畸变中影响较大的径向畸变而忽略切向畸变,用求得的内参矩阵反解畸变参数。

设无畸变像素坐标、成像平面坐标分别为[u^v^]T\left[ \begin{matrix} \hat{u}& \hat{v}\\\end{matrix} \right] ^T[u^​v^​]T、[x^y^]T\left[ \begin{matrix} \hat{x}& \hat{y}\\\end{matrix} \right] ^T[x^​y^​​]T;有畸变像素坐标、成像平面坐标分别为[uv]T\left[ \begin{matrix} u& v\\\end{matrix} \right] ^T[u​v​]T、[xy]T\left[ \begin{matrix} x& y\\\end{matrix} \right] ^T[x​y​]T;设内参s=0s=0s=0,则

{u=fux+cuv=fvy+cv{u^=fux^+cuv^=fvy^+cv\begin{cases} u=f_ux+c_u\\ v=f_vy+c_v\\\end{cases}\,\, \begin{cases} \hat{u}=f_u\hat{x}+c_u\\ \hat{v}=f_v\hat{y}+c_v\\\end{cases}{u=fu​x+cu​v=fv​y+cv​​{u^=fu​x^+cu​v^=fv​y^​+cv​​

两式相减,并代入fux=u−cuf_ux=u-c_ufu​x=u−cu​、fvy=v−cvf_vy=v-c_vfv​y=v−cv​以及径向畸变公式

{x^=x(1+κ1r2+κ2r4)y^=y(1+κ1r2+κ2r4)\begin{cases} \hat{x}=x\left( 1+\kappa _1r^2+\kappa _2r^4 \right)\\ \hat{y}=y\left( 1+\kappa _1r^2+\kappa _2r^4 \right)\\\end{cases}{x^=x(1+κ1​r2+κ2​r4)y^​=y(1+κ1​r2+κ2​r4)​

即得

[(u−cu)r2(u−cu)r4(v−cv)r2(v−cv)r4][κ1κ2]=[u^−uv^−v]\left[ \begin{matrix} \left( u-c_u \right) r^2& \left( u-c_u \right) r^4\\ \left( v-c_v \right) r^2& \left( v-c_v \right) r^4\\\end{matrix} \right] \left[ \begin{array}{c} \kappa _1\\ \kappa _2\\\end{array} \right] =\left[ \begin{array}{c} \hat{u}-u\\ \hat{v}-v\\\end{array} \right][(u−cu​)r2(v−cv​)r2​(u−cu​)r4(v−cv​)r4​][κ1​κ2​​]=[u^−uv^−v​]

考虑到

[u^v^1]=K[WC⁣ ⁣ ⁣RC⁣pw0][W⁣⁣XW⁣⁣ ⁣  ⁣ YW⁣⁣Z1]\left[ \begin{array}{c} \hat{u}\\ \hat{v}\\ 1\\\end{array} \right] =\boldsymbol{K}\left[ \begin{matrix} _{\boldsymbol{W}}^{\boldsymbol{C}}\;\!\!\!\boldsymbol{R}& ^{\boldsymbol{C}}\!\boldsymbol{p}_{w_0}\\\end{matrix} \right] \left[ \begin{array}{c} ^{\boldsymbol{W}\!}\!X\\ ^{\boldsymbol{W}\!}\!\!\:\!\:Y\\ ^{\boldsymbol{W}\!}\!Z\\ 1\\\end{array} \right]⎣⎡​u^v^1​⎦⎤​=K[WC​R​Cpw0​​​]⎣⎢⎢⎡​WXWYWZ1​⎦⎥⎥⎤​

对于MMM幅标定板图片,每张图片取NNN个角点,则可构造非齐次线性方程

D2MN×2κ=d2MN×1\boldsymbol{D}_{2MN\times 2}\boldsymbol{\kappa }=\boldsymbol{d}_{2MN\times 1}D2MN×2​κ=d2MN×1​

其中κ=[κ1κ2]T\boldsymbol{\kappa }=\left[ \begin{matrix} \kappa _1& \kappa _2\\\end{matrix} \right] ^Tκ=[κ1​​κ2​​]T即为畸变系数。通过最小二乘法进行回归

κ=(DTD)−1DTd{\boldsymbol{\kappa }=\left( \boldsymbol{D}^T\boldsymbol{D} \right) ^{-1}\boldsymbol{D}^T\boldsymbol{d}}κ=(DTD)−1DTd

即得畸变系数

4 去畸变原理与实战

综合上面两节,给出去畸变的原理

  • 准备张氏标定法的标准棋盘格,用相机对其进行不同角度拍摄,得到一组图像
  • 忽略畸变,每张标定板可通过世界坐标与像素坐标的关系,求解二者间的单应性矩阵,用于反解相机内参矩阵;忽略切向畸变与内参矩阵误差,反解径向畸变参数
  • 利用L-M(Levenberg Marquardt)等非线性迭代优化算法对上述参数进行优化,得到最终的内参矩阵与畸变参数。

按照上面的原理,我们将相机标定与去畸变的代码写出来

/** @breif:采用张氏标定法标定相机并生成标定文件.txt* @param[in]:folderPath->标定板图像集的文件夹路径;* @param[in]:boardSize->标定板上每行、列的内角点数;* @param[in]:realSizePerBox->实际测量的标定板棋盘格几何尺寸,与相机矩阵单位pix/mm对应,Unit:mm;* @param[in]:savePath->标定文件.txt的保存路径;* @retval:None*/
void cameraCalibration(String folderPath, Size boardSize, Size realSizePerBox, String savePath)
{std::vector<cv::String> fileNames;                       // 存放标定图片文件名的序列cv::glob(folderPath, fileNames);                     // 将标定文件夹中的文件名读取到序列Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); // 像机内参矩阵Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0)); // 像机畸变系数:k1,k2,p1,p2,k3vector<Mat> tvecsMat;                                  // 相机外参->旋转向量vector<Mat> rvecsMat;                                 // 相机外参->平移向量int imgCnt = 0;                                            // 图像数量vector<int> ptCnt;                                     // 图像中角点的数量Size imgSize;                                            // 图像尺寸vector<Point2f> imgPtBuffer;                           // 缓存每幅图像上检测到的角点vector<vector<Point2f>> imgPtSequence;                  // 检测到的所有角点序列,Unit:pixvector<vector<Point3f>> realImgPtSequence;             // 检测到的所有角点序列,Unit:mmdouble totalErr = 0.0;                                 // 所有图像的重投影误差和/*========================================= 像素平面角点坐标提取 =========================================================*/for (size_t i = 0; i < fileNames.size(); ++i){imgCnt++;printf("read the number %d image\n", i+1);Mat imgInput = imread(fileNames[i]);ptCnt.push_back(boardSize.width * boardSize.height); // 初始化每幅图像中的角点数量,假定每幅图像中都可看到完整标定板if (imgCnt == 1)                              //读入第一张图片时获取图像宽高信息{imgSize.width = imgInput.cols;imgSize.height = imgInput.rows;}if (findChessboardCorners(imgInput, boardSize, imgPtBuffer) == 0)  // 提取ChessBoard类型角点{printf("can't find the corner point of image number %d, please check!\n", i);return;}else{Mat imgGray;cvtColor(imgInput, imgGray, CV_RGB2GRAY);  //图像灰度化find4QuadCornerSubpix(imgGray, imgPtBuffer, Size(11, 11));       //对粗提取的角点进行亚像素精确化imgPtSequence.push_back(imgPtBuffer);  }}/*========================================= 几何平面角点坐标提取 =========================================================*/for (int i = 0; i < imgCnt; i++){vector<Point3f> tempPtSetPerImg;for (int j = 0; j < boardSize.height; j++){for (int k = 0; k < boardSize.width; k++){Point3f realPoint;realPoint.x = j * realSizePerBox.width;realPoint.y = k * realSizePerBox.height;realPoint.z = 0;                        // 张氏标定法假设标定板放在世界坐标系中z=0的平面上tempPtSetPerImg.push_back(realPoint);}}realImgPtSequence.push_back(tempPtSetPerImg);}/*======================================== 相机标定与重投影误差计算 ======================================================*/calibrateCamera(realImgPtSequence, imgPtSequence, imgSize, cameraMatrix, distCoeffs, rvecsMat, tvecsMat);totalErr = calReprojectErr(realImgPtSequence, imgPtSequence, rvecsMat, tvecsMat, cameraMatrix, distCoeffs, ptCnt);
}

看看效果,只看标定格:

本文的完整工程代码请通过下方名片联系我获取


计算机视觉教程0-4:手推张正友标定法,详解图像去畸变(附代码)相关推荐

  1. 工业相机标定(张正友标定法)

    目录 相机标定的概念 a. 相机标定的定义 b. 相机标定的目的 相机标定的过程 a. 标定板选择 b. 标定板摆放及拍摄 c. 标定板角点提取 张正友标定法 a. 反解相机矩阵 b.反解畸变系数 使 ...

  2. 【三维重建】相机标定:张正友标定法

    系列文章目录 本系列开始于2022.12.25,开始记录三维重建项目课题研究时的学习笔记,其中主要分为以下几部分组成: 一.相机成像及坐标系之间的转换关系 二.相机标定:张正友标定法 三.特征检测与匹 ...

  3. 针孔相机标定-基于张正友标定法

    针孔相机标定 前段时间曾经做过一段时间的摄像头标定,这里对以前做的事情做一个总结.首先,介绍一下针孔相机的标定吧,主要还是代码解析和一些细节说明,为了让自己更好的理解相机标定.当时做摄像头标定是为了实 ...

  4. 单目相机标定实现--张正友标定法

    文章目录 一:相机坐标系,像素平面坐标系,世界坐标系,归一化坐标系介绍 1:概述 公式 二:实现 1:整体流程 4:求出每张图像的单应性矩阵并用LMA优化 5:求解理想无畸变情况下的摄像机的内参数和外 ...

  5. 相机模型及张正友标定法

    针孔相机模型 针孔相机模型是实际研究中最常用的模型.针孔是一个中间有一个小孔的假想墙壁,光只能从小孔通过. fff是摄像机焦距,ZZZ是摄像机到物体的距离,XXX是物体长度,是图像平面上的物体长度.由 ...

  6. 基于亚像素的图像测量仪标定算法(满视场棋盘格,张正友标定法)

    图像测量仪对测量的精度极高,能达到0.001毫米,所有的图像边缘分割和摄像头标定,都在亚像素级水平上进行.目前我们能做到1/100个像素的提取.图像测量仪的关键部分在于亚像素分割.亚像素分割算法各种各 ...

  7. matlab圆形标记,toolbox_calib 改进过的张正友标定法,可以用于使用圆形标记点 板的相机 。 matlab 266万源代码下载- www.pudn.com...

    文件名称: toolbox_calib下载  收藏√  [ 5  4  3  2  1 ] 开发工具: matlab 文件大小: 946 KB 上传时间: 2014-02-23 下载次数: 39 提 ...

  8. 张正友标定法:A Flexible New Technique for Camera Calibration

    张正友标定法:A Flexible New Technique for Camera Calibration Abstract MOTIVATIONS BASIC EQUATIONS Notation ...

  9. 标定代码:张正友标定法(matlab工具箱自编程序)(matlab)

    张正友标定法原理 张正友标定法,一般采用二维棋盘格标定板. 标定板制作链接:棋盘格 张正友标定法推导过程

  10. Python-OpenCV相机标定、张正友标定法

    一.相机标定介绍: 相机标定是进行视觉测量和定位的基础工作之一,标定参数准确与否直接关系到整个系统的精度,为此根据自己项目中的经验及参考相关的商用视觉软件的做法将相机标定过程中标定图片的获取过程中需要 ...

最新文章

  1. LA3942字典树+递推
  2. addonsmaker怎么制作_addonsmaker
  3. 《openssl 编程》之大数
  4. 别傻啦,不会高数,你连人话都听不懂
  5. RTSP鉴权认证之基础认证和摘要认证
  6. python全局变量怎么删除_python 全局变量怎么改
  7. 洛谷 P2257 YY的GCD
  8. asp.net 页面数据导入word模板
  9. 解决IE、firefox浏览器下JS的new Date()的值为Invalid Date、NaN-NaN的问题
  10. CCF NOI1075 F函数
  11. php装curl拓展出错
  12. 2021-01-21
  13. 自动化测试基础篇--Selenium弹出框alert
  14. JAVA计算机毕业设计在线购书商城系统Mybatis+源码+数据库+lw文档+系统+调试部署
  15. python爬虫ip限制_爬虫访问中如何解决网站限制IP的问题?
  16. 使用Layui搭建后台管理界面
  17. 安装.net补丁后mscorsvw.exe占CPU100%的问题
  18. 数字信号处理之数字混频
  19. sql server实现简繁转换
  20. Vertica资源池

热门文章

  1. 单片机算法c语言程序,51单片机PID的算法实现程序C语言
  2. 计算机与不确定性原理,傅里叶变换和不确定性原理
  3. 同指数幂相减公式_指数相减.即所以同底数幂的除法法则.PPT
  4. 无线城域网-无线广域网
  5. CAD 系统变量参数大全
  6. mfc 调用绿色版的Foxit Reader / 迷你pdf阅读器.exe的同时打开一个pdf文件
  7. JAVA实现从Linux服务器上下载文件
  8. 解决:应用程序无法启动,因为应用程序的并行配置不正确
  9. 什么是浏览器指纹识别
  10. [超详细] 在Edge/Chrome浏览器上为B站开启HEVC硬解和AV1硬解(支持4K120Hz、8K、HDR真彩,杜比视界、杜比全景声)