当前位置: 首页 > 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.gsyq.cn/news/1644275.html

相关文章:

  • AI Agent框架:从模型驱动到任务执行的关键工程化实践
  • 059、RealBasicVSR 实战:真实场景视频超分的退化建模与优化技巧
  • 信息论与编码课程调研报告:连续AWGN信道中香农容量极限的数学推导与MATLAB仿真实现(P124302067 吴晨晨,P124302076 吕欣欣)
  • AI编程接单实战复盘:Claude Code 4天完成电商开票系统迭代,5000元私活全过程
  • Dell PERC H330/H730 RAID 卡实战:R730 创建 RAID-5 与删除配置 12 步详解
  • 电话机器人厂家哪个好
  • 德明利:从布头生意到整布豪赌,存储赛道的独特玩家能否再赢一局?
  • 第2章 异常
  • 村长团队教你用3dMax + ZM3制作GTA5水源教程
  • YOLOv10模型改进-Neck改进-第74篇:YOLOv10改进策略【Neck】| FPN-DCN可变形卷积
  • 蓝速科技会议电子门牌部署与可视化管控指南
  • 通达信竣宝绝密主升连板量化选股与量化交易指标公式抓底部启动牛股 主力机构游资启动选股公式 波段擒龙决
  • 实用微信QQ防撤回补丁完整指南:告别消息丢失的终极方案
  • 如何免费解锁9大网盘高速下载权限:完整实战指南
  • LeetCode第三方解绑定 微信一个账号,手机号一个账号
  • 第19章|有章可循:Rules 规则系统深度剖析
  • AI编程时代程序员生存指南:从工具实操到能力重塑
  • AI Agent平台选型实战:从LangChain到CrewAI的10大开源方案深度测评
  • 连锁超市收银系统选什么?千店实测与商拓深度测评
  • 终极指南:一键修复Windows软件运行失败的Visual C++运行库问题
  • 实验七:自媒体运营分析-数据清洗与预处理
  • 项目版本管理的最佳实践:云效飞流Flow篇
  • XSS-Labs通关秘籍:7种花式绕过技巧与实战解析
  • 要不要弃坑 Cursor?一个重度用户的真实纠结
  • 从提示词工程到技能工程:Agent Skill开发实战指南
  • 《智人之上》第一章「信息是什么」读后总结
  • AI Agent开发实战指南:从概念到落地,手把手构建智能体应用
  • 拒绝“月半”体质!在家练出高级感,我的自律养成方案
  • 解决Windows无法在微软商店安装CodeX问题
  • 从OpenMontage到AI工作流:GitHub趋势揭示的Agent与自动化新范式