当前位置: 首页 > news >正文

什么是相机标定

相机标定(Camera Calibration)是计算机视觉、自动驾驶、机器人(SLAM)以及 AR/VR 领域中不可或缺的“基本功”。

简单来说,相机的镜头就像是一面哈哈镜(多多少少都有畸变),而标定的目的就是帮相机找回“视力”,看清真实的三维世界

下面为你带来一份通俗易懂、包含数学原理与代码实战的相机标定全景指南


一、 核心原理:我们在标定什么?

相机成像的过程,实际上是把**三维世界(World)中的点,映射到相机的二维像素平面(Pixel)上。这个过程可以用四个坐标系的转换来描述:

世界坐标系相机坐标系图像坐标系像素坐标系

标定的核心任务,就是求解两个矩阵(内参和外参)以及一组畸变参数:

1. 相机内参(Intrinsic Parameters)—— 解决“相机本身”的问题

内参是由相机自身的机械和光学结构决定的(如焦距、感光元件大小)。一旦相机组装好并且不失焦,内参就是固定不变的。 内参矩阵通常写为K

  • fx,fy:横向和纵向的焦距(以像素为单位)。
  • cx,cy主点坐标,即相机光轴在图像传感器上的中心点(通常接近图像的正中央)。

2. 相机外参(Extrinsic Parameters)—— 解决“相机摆放”的问题

外参决定了相机在三维世界中的位置和朝向

  • 旋转矩阵R:相机朝哪儿看(俯仰、偏航、翻滚)。
  • 平移向量T:相机在什么位置。
  • 注意:如果相机在移动(比如装在车上),外参是会随着运动实时变化的。

3. 畸变参数(Distortion Coefficients)—— 解决“镜头变型”的问题

普通的透镜(尤其是广角或鱼眼镜头)往往会导致直线变曲线。主要分为两种:

  • 径向畸变(Radial Distortion):由于透镜形状导致,越靠近图像边缘变型越厉害。表现为桶形畸变(鼓起来)或枕形畸变(凹进去)。
  • 切向畸变(Tangential Distortion):由于镜头组装时,透镜与感光芯片(CMOS/CCD)没有完全平行导致。

二、 主流标定方法:张正友标定法

目前工业界和学术界最常用的方案是**“张正友标定法”(Zhang’s Method)。在它问世之前,标定需要搭建昂贵的三维标定物;而张氏标定法只需要一张打印出来的二维黑白棋盘格**,在不同角度拍十几张照片即可。

标定的标准流水线(Workflow):

  1. 准备标定板:打印一张高精度的黑白棋盘格或 ChArUco 标定板(通常贴在平整的刚体表面,如玻璃或碳纤维板上)。
  2. 采集图像:变换不同的角度、距离、高度,拍摄 15∼25 张标定板的照片。
    • 避坑指南:标定板要尽量占满整个画面,特别是图像的四周边缘,因为边缘的畸变最大,只有覆盖到边缘才能准确计算畸变参数。
  1. 提取角点(Corner Extraction):在计算机中识别棋盘格黑白相间的交点。
  2. 优化求解:利用数学优化算法(如 LM 算法),让重投影误差最小,从而解出内参、外参和畸变系数。

三、 代码实战:使用 OpenCV 自动标定

以下是使用 Python 和 OpenCV 实现相机标定的标准脚本。你只需要把拍摄好的照片放到一个文件夹里即可运行。

import cv2 import numpy as np import glob # 1. 设定标定板的参数 # 注意:这里的行列数是黑白格子交点的个数,不是格子的个数! # 例如:一个 9x7 格子的棋盘,内角点是 8x6 CHECKERBOARD = (8, 6) square_size = 25.0 # 单个黑白格子的实际物理边长(单位:毫米 mm) # 定义三维世界坐标系下的棋盘格点坐标 objp = np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32) objp[:, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2) objp = objp * square_size # 存储所有照片的三维世界点和二维像素点 objpoints = [] # 3d points in real world space imgpoints = [] # 2d points in image plane. # 读取文件夹中所有的标定照片 images = glob.glob('calibration_images/*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 2. 寻找棋盘格角点 ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, None) if ret == True: objpoints.append(objp) # 亚像素级角点精准定位(提升标定精度) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) imgpoints.append(corners2) # 可视化角点(可选) cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret) cv2.imshow('Chessboard Detection', img) cv2.waitKey(100) cv2.destroyAllWindows() # 3. 核心步骤:相机标定 # 返回值:ret(重投影误差), mtx(内参), dist(畸变系数), rvecs(旋转外参), tvecs(平移外参) ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) print(f"--- 标定完成 ---") print(f"重投影误差 (Re-projection Error): {ret:.4f} 像素") print(f"相机内参矩阵 (Intrinsic Matrix):\n{mtx}") print(f"畸变系数 (Distortion Coefficients):\n{dist}") # 4. 利用标定结果矫正一张畸变照片 test_img = cv2.imread('calibration_images/test_pic.jpg') h, w = test_img.shape[:2] # 优化内参矩阵 newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h)) # 矫正去畸变 dst = cv2.undistort(test_img, mtx, dist, None, newcameramtx) # 裁剪并保存 x, y, w_box, h_box = roi dst = dst[y:y+h_box, x:x+w_box] cv2.imwrite('calibrated_result.jpg', dst) print("去畸变照片已保存为 'calibrated_result.jpg'")

四、 工业级标定的避坑与评估

拿到标定数据后,你怎么知道标定得准不准?

1. 核心指标:重投影误差(Re-projection Error)

它是指把标定计算出的三维世界点,重新投影回像素平面,与实际拍摄到的角点之间的像素距离

  • 优秀:误差 << 0.5 像素。
  • 合格:误差 << 1.0 像素。
  • 如果误差 >> 1.5 像素,说明部分照片拍糊了、标定板不平整,或者角点识别错误,建议剔除坏照片重新计算。

2. 提高标定精度的实战技巧

关键要素

错误做法

正确做法

画面覆盖率

标定板只在屏幕中心晃悠

必须把标定板移动到图像的四个角落和边缘

角度丰富度

标定板永远平行于相机(正对)

标定板需要产生倾斜角度

(俯仰角度、翻转角度)

光照与对焦

画面有反光、阴影、或者运动模糊

使用高均匀度光源,运动时拿稳停顿

再拍,严禁动态模糊

硬件刚性

打印纸贴在软纸板上,产生肉眼难察的弯曲

必须贴在高平整度

的亚克力板、玻璃或专业定制的铝合金板上



http://www.jsqmd.com/news/1132295/

相关文章:

  • 多相机画面割裂根治方案:MatrixFusion™融合引擎核心原理详解
  • 毕业生必备7款AI写作辅助网站,一站式搞定选题初稿与降AI率
  • How-To: Using the N* stack, part 1
  • 秒杀系统设计核心要点
  • AI Agent框架:从模型驱动到任务执行的关键工程化实践
  • iPhone与Nothing Phone旋转图片操作大不同,无障碍设计为何重要?
  • 【DBX数据库工具技术解析】15MB管理60+数据库的Docker部署指南
  • 别让 AI 直接写接口:前后端联调前,先把这 4 份契约交给它
  • AI编程接单实战复盘:Claude Code 4天完成电商开票系统迭代,5000元私活全过程
  • Dell PERC H330/H730 RAID 卡实战:R730 创建 RAID-5 与删除配置 12 步详解
  • Cursor、Zed、Windsurf:AI原生编辑器的架构级差异解析
  • 信息论与编码课程调研报告:连续AWGN信道中香农容量极限的数学推导与MATLAB仿真实现(P124302067 吴晨晨,P124302076 吕欣欣)
  • 2026年行驶6万公里的新能源汽车,专业底盘整备究竟哪家技术更胜一筹?
  • 059、RealBasicVSR 实战:真实场景视频超分的退化建模与优化技巧
  • Optuna 分布式优化实战:4节点并行加速 CatBoost 超参数搜索
  • Power BI中SUMMARIZE函数实战:构建高性能可审计汇总表
  • Python爬虫经典案例第73篇:新闻聚合平台爬取:Google News数据采集实战
  • 2026年深度检验:10款好用的降AI率网站,部分无限免费降AI!速速码住
  • 密码学算法
  • 【考研】2026/7/5
  • 【地平线 征程 6 工具链进阶教程】QAT 训练常见问题和排查
  • AI 辅助内容生产与网站优化的实践:效率提升在哪、边界在哪
  • PWM+MOS管驱动LED振铃干扰
  • 电话机器人厂家哪个好
  • 德明利:从布头生意到整布豪赌,存储赛道的独特玩家能否再赢一局?
  • Java异常处理深度实战教程:异常管理策略
  • 第2章 异常
  • 村长团队教你用3dMax + ZM3制作GTA5水源教程
  • zxcvbn密码强度评估工具:如何快速提升密码安全性的完整指南
  • 高Tg PCB材料(Tg≥170°C)在无铅制程中的5项性能实测与失效分析