MATLAB相机标定实战:内参、畸变系数与重投影误差详解

发布时间:2026/10/4 8:01:28
MATLAB相机标定实战:内参、畸变系数与重投影误差详解 第一次正儿八经做视觉定位项目我差点被“相机标定”这四个字劝退。网上教程大多在讲原理公式一推就是三四页实际打开MATLAB工具箱后又发现按钮就这么几个点完标定出一堆数字完全不知道对不对。这篇文章把我从原理到实战踩过的坑完整记录下来直接用MATLAB把相机内参、外参、畸变系数标出来并且告诉你每个数字代表什么、怎么判断标得好不好、后期代码里怎么用。想快速上手的视觉方向同学或者已经在用OpenCV标定、想换更直观工具的开发者都可以直接参考。1. 先搞清楚相机标定的核心逻辑内参、外参与畸变1.1 针孔相机模型四个坐标系之间的关系相机标定要解决的第一个问题是把三维空间里的点怎么变成二维图像上的像素这件事用数学模型精确描述出来。绝大多数普通镜头都近似满足针孔相机模型也就是光线通过一个虚拟光心在传感器平面上成像。整个投影过程涉及四个坐标系世界坐标系、相机坐标系、图像物理坐标系、像素坐标系。一个空间点先通过外参旋转矩阵R和平移向量t从世界坐标系变换到相机坐标系再通过内参从相机坐标系投影到像素坐标系。内参矩阵K是核心它的标准形式是K [fx, 0, cx; 0, fy, cy; 0, 0, 1]这里的fx和fy分别是x、y方向上的等效焦距单位是像素。它们和镜头物理焦距f、像素物理尺寸dx、dy的关系是fx f / dxfy f / dy。对于大多数相机dx和dy接近相等所以fx和fy通常很接近但不会完全一样。cx和cy是主点坐标也就是光轴与传感器平面的交点。很多新手会踩一个认知误区以为cx和cy就是图像分辨率的一半。实际上由于镜头安装公差、传感器封装误差主点和图像中心往往有几十个像素的偏差即使分辨率是1920x1080主点也可能落在(950, 545)这类位置而不是(960, 540)。所以标定得到的cx、cy是实测值不要在后期代码里强行改成分辨率中心。1.2 畸变模型镜头不是完美的针孔模型是理想模型真实镜头还存在畸变。最常见的畸变是径向畸变用生活化类比来说就是透过一个老花镜边缘看东西直线会变弯。径向畸变用k1、k2、k3三个系数描述桶形畸变时k1为负枕形畸变时k1为正。另一个是切向畸变主要是透镜和传感器平面不完全平行造成的装配误差用p1、p2两个系数描述。MATLAB标定工具箱输出一套完整的畸变系数畸变模型公式如下x_distorted x * (1 k1 * r² k2 * r⁴ k3 * r⁶) 2 * p1 * x * y p2 * (r² 2x²)y_distorted y * (1 k1 * r² k2 * r⁴ k3 * r⁶) p1 * (r² 2y²) 2 * p2 * x * y这里x、y是归一化平面坐标r² x² y²。注意k3在高畸变镜头比如广角、鱼眼里影响很大普通工业镜头k3通常很小甚至可能在标定时被优化到接近零。如果你用的是OpenCV老版本默认只估计k1、k2、p1、p2新版本也可以加入k3需要手动设置标志位。MATLAB的Camera Calibrator默认会估计k1、k2、k3输出里如果k3那一项很小属于正常现象。1.3 棋盘格与张正友法为什么不能只拍一张图标定算法最主流的是张正友标定法也就是用平面棋盘格作为标定物通过多张不同姿态的棋盘格图像计算相机内参。它之所以成为工业界的事实标准是因为棋盘格的角点检测简单可靠而且平面标定板制作成本低、精度高。这里有一个很多人问过的问题为什么必须拍很多张不同角度的图理论上如果忽略畸变两张不同姿态的棋盘格图就能求解内参但实际标定时要考虑角点检测噪声、镜头畸变、标定板加工误差只有多张姿态差异明显的图像才能在最小二乘优化中把这些误差平均掉。我实测下来15到20张是比较合适的数量少于10张时结果稳定性明显变差内参矩阵可能每次标定都差几十个像素。采集的关键不只是数量还有姿态多样性。棋盘格的空间姿态应该像扇子一样展开有俯仰、有偏航、有左右倾斜同时让标定板出现在画面的不同区域。如果只是在同一平面内平移或缩放姿态之间相关性太高矩阵病态标出来的畸变系数会非常不靠谱。2. 开工前的准备工具选型与数据采集2.1 MATLAB Camera Calibrator 与 OpenCV 怎么选我见过很多人在标定工具上纠结其实没必要。OpenCV和MATLAB的核心算法都源于类似的原理标定结果在精度上没有本质差距差别主要在操作体验和工程化便利性上。MATLAB Camera Calibrator的最大优势是交互式剔帧。标定完一版后你可以直接看到每张图的平均重投影误差柱状图哪张图误差大就右键删掉再重新标定整个过程鼠标点几下就完成。OpenCV虽然也能在代码里筛选但你要自己写循环、画角点、看误差调试效率低不少。另一方面如果需要在服务器上批量自动标定几千张图或者标定流程要嵌入到独立工程里OpenCV更适合。我个人建议做课题研究、写论文、做算法验证用MATLAB做产品化批量标定用OpenCV。这篇文章以MATLAB为主线但标定结果的物理含义和操作逻辑两种工具完全相通。MATLAB环境下运行cameraCalibrator命令即可打开图形化工具前提是安装了Computer Vision Toolbox和Image Processing Toolbox。这两个工具箱在MATLAB安装时选上即可不建议用任何非官方渠道的版本。2.2 标定板制作打印、裱板与尺寸测量标定板不需要买昂贵的陶瓷板。对大多数场景自己打印加硬性裱板完全够用。制作时重点注意三件事纸面不能反光、板面不能弯曲、格子边长必须测准。打印标定板建议用哑光纸或普通A4纸不要用光面铜版纸不然拍摄时有反光点角点检测会出问题。打印后贴在硬板上硬板可以是亚克力板、铝塑板或者厚纸板。我一开始图省事把打印纸直接贴在快递纸箱上结果板面本身有起伏标定出来的畸变系数明显异常。后来换成3毫米亚克力板问题一次性解决。格子边长的测量是个容易忽略的坑。MATLAB标定时会让你输入棋盘格一个格子的物理边长单位是毫米这个数值是后续所有几何计算的基准。如果实际边长是24.5毫米你填成25毫米最终标定出的焦距会整体偏离约2%。所以打印完要拿游标卡尺在标定板的多个位置测量取平均值填入。我习惯测三组数据如果最大值和最小值相差超过0.2毫米说明打印变形严重需要重新打印。生成标定板图案的方式很简单。OpenCV里可以用drawChessboardCorners生成9x6的棋盘格图MATLAB命令行也可以用checkerboard函数生成保存成图片后再打印。这里涉及一个易混淆的概念9x6通常指内部角点数为9列6行对应实际棋盘格方块是10列7行。MATLAB标定工具不需要你输入角点数量它会自动检测但你在制作标定板时自己对数量要心里有数。2.3 采图规范15张图怎么拍才有效标定精度好不好一半在数据采集。我自己总结了一套采图流程按这个流程走标定结果基本一次到位。第一拍摄距离要覆盖实际工作场景。如果做桌面近景定位标定板就不要拿得很远拍如果做室外远距离测距标定板也不要怼到镜头前。畸变在不同距离上的表现不一样贴近实际使用距离标定结果才最能反映真实验收环境。第二姿态要丰富。15到20张图里要包含左右旋转、上下俯仰、倾斜45度等组合同时移动标定板在画面中的位置让角落和边缘都能被覆盖到。不要只做“距离缩放”那样所有棋盘格平面都平行于像平面姿态之间没有足够差异求解出的畸变系数会出现严重的病态。第三光照要均匀。避免强光直接照射标定板造成过曝避免闪光灯避免窗户反光。过曝后白色格子连成一片角点检测算法会在错误位置找角点而且你不会立刻发现直到重投影误差超了才开始排查。第四图像不能模糊。手持相机拍摄容易在低速快门下产生运动模糊建议把相机放在三脚架上或者调整到足够快的快门速度。模糊图片在角点检测时可能会出现亚像素定位偏差导致整体误差被拉高。第五标定板尽量占画面的三分之一以上并且完整出现在画面内。如果边缘被裁剪掉一部分那一侧的角点信息缺失标定出的畸变模型在边缘区域外推不可靠。如果是Intel RealSense D435i这类深度相机标定RGB内参时需要固定RGB传感器的参数建议关闭深度流后拍摄避免红外图案投影到RGB画面中形成异常纹理干扰。D435i出厂自带标定数据但如果要做高精度应用重新标定是推荐的。2.4 软件环境准备好之后的第一件事打开MATLAB确认工具箱可用后命令行输入cameraCalibrator会弹出Camera Calibrator窗口。界面左侧是图像列表右侧有操作按钮。第一次打开可能有点懵其实完整流程只有五步添加图像、输入格子尺寸、检测角点、标定、导出参数。如果是旧版本MATLAB界面布局可能有细微差别但功能逻辑一致。建议使用较新的版本工具会在标定后自动显示重投影误差分布还能一键剔除超标图像对新手友好很多。3. MATLAB相机标定实战从角点检测到参数导出的完整操作3.1 导入图片与设置棋盘格尺寸点工具栏上的Add Images选择采集到的所有标定图片。MATLAB会弹出一个对话框让你输入棋盘格尺寸也就是每个格子的物理边长。这里单位是毫米务必填入实测值不要填打印分辨率、不要填角点数量。点击确定后MATLAB开始自动检测棋盘格角点。检测成功的话每张图上会叠加彩色圆点标记以棋盘格左上角为原点生成坐标系。检测失败或某张图只检测到部分角点图像列表里会显示警告图标这时就该判断是删掉该帧还是重新拍摄。一个容易被忽略的点MATLAB默认会检测完整的棋盘格角点网格如果标定板在画面中有遮挡或者某一行格子被光线吃掉检测结果会缺行缺列。这时候最好的处理方式是直接删除该图不要强行保留一张残缺角点数据去凑姿态数量。3.2 角点检查与不合格帧剔除导入完成后先逐张点击图像列表检查角点标记位置和真实棋盘格交叉点是否严格对齐。这一步很枯燥但非常必要。即使检测结果看起来都在棋盘格上也可能存在整体偏移一个像素的情况这种系统性误差在重投影误差里看不出来。角点检查没大问题后直接点CalibrateMATLAB会立即计算并显示标定结果。右侧会展示每张图的平均重投影误差柱状图还有一个总体的平均误差数值。这个数值是衡量标定质量的第一指标。经验数值如下平均重投影误差小于0.3像素标定质量优秀0.3到0.5像素可以接受大于0.5像素说明有几张图有问题或者标定板变形不建议直接使用。这里说的误差单位是像素也就是检测到的角点位置与按模型投影回去的角点位置之间的距离。可以理解成“用模型反算回去角点位置差了多少个像素”。理想情况下畸变模型和内参完全准确反投影位置应该和检测位置重合误差接近0。如果平均误差偏高重点看柱状图里明显凸起的几帧右键选择删除。删除后重新Calibrate重复几次直到整体平均误差降下来。我见过一个项目标定完平均误差0.8像素删掉三张在强光下拍的模糊图后直接降到0.25像素。选帧质量对结果的影响就是这么直接。注意不要为了追求极低误差把所有图片都删到只剩三四张。虽然平均误差会很好看但内参估计会退化。衡量标定结果时平均误差和内参稳定性要一起看。3.3 标定计算与结果解读标定完成后界面左侧会列出内参矩阵、畸变系数、每张图的外参。一个典型的标定结果长这样内参矩阵像素 [1430.23, 0, 960.52; 0, 1428.71, 540.18; 0, 0, 1]径向畸变系数[k1, k2, k3] [-0.045, 0.023, 0.0051]切向畸变系数[p1, p2] [0.0002, -0.0003]看到这组数字怎么判断是否合理首先看fx和fy。对于大多数工业相机和普通镜头fx和fy应该很接近相差通常在几个像素之内。如果两者相差几十甚至上百像素要么是像素本身不是方形极少见要么是标定过程出了问题。其次看主点cx、cy。它们应该落在图像分辨率中心附近但允许有合理偏差。偏差上百像素也可以接受只要重投影误差低、畸变系数稳定。然后看畸变系数量级。普通工业镜头k1一般在-0.1到0.1之间k2比k1小一个量级k3更小。如果标定出k1-0.5这种夸张数值大概率是标定板弯曲、格子尺寸填错、或者有效图像数量太少。最后点开每一帧看外参Extrinsics的3D可视化。这些网格平面应该分布在相机前方不同的角度如果所有平面都挤在一起说明姿态多样性不足需要补拍。我这里补充一个D435i相关经验这类深度相机的RGB镜头视场角较大边缘畸变比普通工业镜头更明显标定时尤其要多拍边缘区域的棋盘格姿态否则去畸变后图像边缘会出现波纹状扭曲。3.4 参数导出与代码接入标定完成后点Export - Export Camera Parameters工作区会出现一个cameraParams对象。这个对象包含了后续代码的一切标定信息包括IntrinsicMatrix、RadialDistortion、TangentialDistortion、WorldPoints等。在命令行里可以直接验证去畸变效果load(cameraParams.mat); I imread(test_image.jpg); Iu undistortImage(I, cameraParams); imshowpair(I, Iu, montage);左右对比可以看到边缘直线的弯曲被修正。这里有个非常重要的坑MATLAB的cameraParams.IntrinsicMatrix是内参矩阵的转置形式也就是K的转置不是K本身。如果你要把参数导出到OpenCV的C或Python代码中使用必须做一次转置再填入cameraMatrix。像素坐标和相机坐标换算时最基础的使用方式如下。给定一个像素坐标(u, v)先归一化到相机坐标系x_norm (u - cx) / fx y_norm (v - cy) / fy这个归一化坐标是后续测距、三维重建、PnP解算的前提。很多人在这一步直接拿像素坐标去算夹角忽略了先归一化结果距离计算偏差一大截。如果工程里还要做双目相机标定MATLAB提供了stereoCameraCalibrator工具在完成左右目各自的内参标定后可以用棋盘格同步采集的左右图像对直接估计两相机之间的旋转矩阵和平移向量。而相机和IMU联合标定、相机与雷达联合标定这一类应用也都是以准确的单目内参为前提的内参不准后面全是白做。至于9点标定算法它其实是针对机械臂或运动平台的像素坐标到物理平台坐标映射通常属于手眼标定范畴和本文讨论的内参标定不是一回事。但如果你要做高精度抓取内参标定一定是9点标定之前的必要步骤否则平台坐标和图像坐标的关联会被镜头畸变带偏。在C工程里使用标定结果时最省事的做法是导出cameraParams.mat后用MATLAB Compiler生成动态库或者把内参和畸变系数写成文本配置在OpenCV里读入cv::Mat cameraMatrix (cv::Mat_double(3,3) 1430.23, 0, 960.52, 0, 1428.71, 540.18, 0, 0, 1); cv::Mat distCoeffs (cv::Mat_double(1,5) -0.045, 0.023, 0.0051, 0.0002, -0.0003);注意这条代码里distCoeffs的顺序是[k1, k2, k3, p1, p2]而MATLAB里如果直接把RadialDistortion和TangentialDistortion拼接顺序是[k1, k2, k3, p1, p2]对应关系不要搞反。4. 相机标定常见问题与高精度避坑经验4.1 标定失败或精度差的排查表我在实际过程中把容易遇到的问题整理成一个排查表基本覆盖了90%的标定翻车场景。现象可能原因解决方法平均重投影误差大于1像素某几帧图片模糊、角点检测错位、标定板弯曲逐帧查看误差柱状图删除误差最高的帧重新标定某张图检测不到角点反光、过曝、标定板边缘被裁剪调整光照避开反光角度重新拍摄检测到的角点网格缺行缺列棋盘格部分遮挡、白色格子连成一片删除该帧或用完整标定板重新拍摄k1畸变系数绝对值大于0.3格子尺寸填错、图像数量太少、姿态单一重新测量格子边长补拍姿态丰富的图像fx和fy相差过大像素尺寸设置错误、标定板变形检查打印是否变形确认图像没有拉伸缩放每次标定结果差异大采集姿态不够多样、图像数量不足重拍至少15张以上覆盖画面九宫格区域去畸变后图像边缘波纹状扭曲边缘区域标定数据不足增加标定板位于画面边缘的姿态图像4.2 我的采集与标定习惯总结踩过几轮坑之后我给自己定了一套固定流程每拿到一台新相机都按这个走标定效率提升非常明显。采集前先用胶带把标定板固定在硬板上四角都要贴紧确保板面完全平直。拍摄时优先用三脚架如果必须手持就提高快门速度防止动态模糊。整个标定过程里千万不要碰镜头变焦环和对焦环。对焦环尤其重要很多自动对焦镜头在每次拍摄时会重新对焦导致焦距轻微变化。我处理的办法是切换到手动对焦模式对准标定板中心锁焦然后保持这个状态拍完全部图像。拍摄姿态上我给自己定了一个目标每一张图都要同时存在“旋转”和“平移”的变化。拍一张正对的拍一张左右转动约30度的拍一张上下倾斜约30度的再拍一张旋转超过45度的。同时移动标定板到画面左上、右上、左下、右下、中心五个区域确保镜头边缘的畸变信息被充分观察到。保存数据时我会在项目目录下建立类似calib_20250115_iphone12_main/的文件夹里面同时存放原始图片、标定结果.mat文件、以及一个记录文件。记录文件里写清楚相机型号、分辨率、格子边长、采集距离范围、标定平均误差。一个月后回头再标定时这些记录能帮你快速判断当前结果是否可信。另外不要复用网上找来的标定图片也不要直接拿别人标定好的参数替换自己的相机。每台相机、每个镜头、每一次分辨率设置都必须单独标定。即使是两台同型号相机内参也会有细微差异工业相机之间主点位置差几十个像素都是正常的。4.3 进一步扩展从单目内参到系统标定单目内参标定是所有视觉标定工作的地基。如果你做的是双目立体视觉完成左右目内参标定后用stereoCameraCalibrator做立体标定得到的是两相机坐标系之间的旋转平移关系。这个关系在三角测距、深度估计中直接决定三维重建精度。如果做的是相机与IMU联合标定思路就不同了。你需要一个包含IMU数据的采集序列通过运动激励让相机和IMU同时感受到充分的旋转和加速度再用kalibr这类工具离线优化出相对外参和时间延迟。这里的先决条件同样是相机内参足够准确否则所有后续优化都会带着内参误差一起收敛到错误解。在自动驾驶或者机器人项目里相机与激光雷达联合标定也是常见需求。不管是标定到Radar还是LiDAR通用的做法都是让标定板同时出现在相机视野和雷达点云中然后找平面特征做配准。这类联合标定工具在ROS2和Autoware生态里都有现成方案但底层依赖的还是可靠的单目内参。做这些扩展之前建议先把自己手里的MATLAB单目标定流程跑得滚瓜烂熟理解内参矩阵、畸变系数、重投影误差这几个核心概念。地基打牢了后面任何标定需求都只是换一个优化目标的问题。最后再分享一个我每次标定后都会做的验证小技巧找一张有明显直线边缘的实景照片比如室内门框、走廊踢脚线、停车位边线用undistortImage去畸变后在图片编辑器里拉一条参考线比一下直线边缘是否真正变直。如果边缘线笔直说明标定质量基本可靠如果边缘线还是弯的即使重投影误差显示0.2像素也要回去重新检查数据采集过程。这个肉眼验证法不依赖任何额外设备却帮我筛掉过好几次“数值好看但实际畸变模型不合理”的标定结果。标定这件事软件操作只占一成九成功夫都在数据采集和数据检查上把这一步做好后续的所有视觉算法才有底气。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询