1. 相机内参标定基础

任务目标

使用棋盘格标定板对相机进行内参标定,获取焦距、主点及畸变系数,并评估重投影误差。本案例使用OpenCV的findChessboardCorners与calibrateCamera完成标定,输出相机内参矩阵与畸变系数,并以重投影误差作为标定质量指标。

环境与依赖

  • Python 3.8+
  • OpenCV(opencv-python)
  • NumPy
  • 准备10~20张不同角度拍摄的棋盘格图像(如10×7内角点棋盘格),图像分辨率需一致

关键完整代码

import cv2
import numpy as np
import glob

# 棋盘格内角点尺寸(列, 行)
CHECKERBOARD = (9, 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 *= square_size

obj_points = []  # 3D点
img_points = []  # 2D点

images = glob.glob('calib_images/*.jpg')

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, 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, CHECKERBOARD, corners2, ret)
        cv2.imshow('Chessboard', img)
        cv2.waitKey(100)

cv2.destroyAllWindows()

# 相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
    obj_points, img_points, gray.shape[::-1], None, None
)

print("内参矩阵:\n", mtx)
print("畸变系数 (k1, k2, p1, p2, k3):\n", dist.ravel())

# 重投影误差评估
total_error = 0
for i in range(len(obj_points)):
    imgpoints2, _ = cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(img_points[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
    total_error += error

mean_error = total_error / len(obj_points)
print(f"平均重投影误差: {mean_error:.4f} px")

运行方式

  1. 创建目录calib_images/,放入10~20张棋盘格照片(建议不同角度、不同距离)。
  2. 安装依赖:pip install opencv-python numpy
  3. 运行脚本:python camera_calib.py

验证方法与判定标准

  • 角点检测成功:运行过程中每张图像会弹出窗口显示检测到的棋盘格角点,若某张图像检测失败(无窗口显示),该图像会被自动跳过。
  • 标定输出:程序打印内参矩阵(含fx, fy, cx, cy)与5个畸变系数。
  • 通过条件:平均重投影误差小于0.5像素,表明标定精度良好;若误差大于1像素,建议剔除模糊或角点检测质量差的图像后重新标定。

常见问题

  • 检测不到角点:确认棋盘格内角点数量与CHECKERBOARD一致(例如9×6表示每行9个内角点、每列6个内角点);避免反光、过曝或图像过暗。
  • 标定误差偏大:增加图像数量(15张以上),并确保棋盘格在画面中占据足够面积且覆盖不同区域(中心、四角、倾斜)。