1. 相机标定基础
任务目标
使用棋盘格标定板对单目相机进行标定,获取相机内参矩阵和畸变系数。本案例使用OpenCV的findChessboardCorners和calibrateCamera完成标定,并输出重投影误差作为标定质量指标。
环境与依赖
- Python 3.8+
- OpenCV(
pip install opencv-python) - NumPy(
pip install numpy) - 准备一张打印的棋盘格标定板(如10×7内角点),从不同角度拍摄15~20张照片
关键完整代码
import cv2
import numpy as np
import glob
# 棋盘格内角点数(列,行)
CHESSBOARD_SIZE = (9, 6)
SQUARE_SIZE_MM = 25.0 # 每个方格边长(毫米),用于生成世界坐标
# 1. 准备对象点(世界坐标系中的棋盘格角点坐标)
objp = np.zeros((CHESSBOARD_SIZE[0] * CHESSBOARD_SIZE[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:CHESSBOARD_SIZE[0], 0:CHESSBOARD_SIZE[1]].T.reshape(-1, 2)
objp *= SQUARE_SIZE_MM
obj_points = [] # 所有图像的对象点
img_points = [] # 所有图像的图像点
# 2. 读取标定图像并提取角点
images = glob.glob('calib_images/*.jpg')
if len(images) == 0:
raise FileNotFoundError("未找到标定图像,请将图像放入 calib_images/ 目录")
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, CHESSBOARD_SIZE, None)
if ret:
obj_points.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)
img_points.append(corners2)
# 可视化角点(可选)
cv2.drawChessboardCorners(img, CHESSBOARD_SIZE, corners2, ret)
cv2.imshow('Corners', img)
cv2.waitKey(100)
else:
print(f"警告:{fname} 中未检测到棋盘格,已跳过")
cv2.destroyAllWindows()
if len(obj_points) < 5:
raise RuntimeError(f"有效标定图像不足(仅 {len(obj_points)} 张),至少需要5张")
# 3. 执行相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
obj_points, img_points, gray.shape[::-1], None, None
)
# 4. 输出标定结果
print("=== 相机内参矩阵 ===")
print(mtx)
print("\n=== 畸变系数 (k1, k2, p1, p2, k3) ===")
print(dist.ravel())
print(f"\n重投影误差: {ret:.4f} 像素")
# 5. 保存标定结果
np.savez('camera_calib.npz', mtx=mtx, dist=dist, ret=ret)
print("\n标定结果已保存至 camera_calib.npz")
运行方式
- 创建目录
calib_images/,将不同角度拍摄的棋盘格照片(.jpg)放入其中 - 将上述代码保存为
calibrate.py,在终端运行:python calibrate.py
验证方法与判定标准
- 角点检测:运行过程中每张图像会弹出窗口显示检测到的棋盘格角点(彩色圆圈叠加),确认所有有效图像均正确识别
- 重投影误差:程序输出的
ret值应小于0.5像素。该值表示标定板角点的世界坐标重投影到图像上的平均像素偏差,越小说明标定精度越高 - 内参合理性:检查内参矩阵中
fx和fy(焦距,单位像素)是否接近图像宽度的1~2倍量级;cx、cy(主点)应接近图像中心坐标 - 结果文件:确认当前目录生成
camera_calib.npz文件,包含内参矩阵和畸变系数
常见问题
- 检测不到棋盘格:确保棋盘格完整出现在画面中且光照均匀;尝试调整
CHESSBOARD_SIZE为实际内角点数(如10×7棋盘对应(9,6)) - 重投影误差过大(>1像素):删除模糊或低分辨率的图像;增加拍摄角度变化(倾斜、旋转);确保标定板平整
- 图像数量不足:至少需要5张有效图像,建议15~20张覆盖不同距离和角度