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")

运行方式

  1. 创建目录calib_images/,将不同角度拍摄的棋盘格照片(.jpg)放入其中
  2. 将上述代码保存为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张覆盖不同距离和角度