1. 相机内参标定基础
任务目标
使用OpenCV对棋盘格标定板图像进行相机内参标定,输出相机矩阵(焦距与主点)和畸变系数,并通过重投影误差评估标定质量。
环境依赖
- Python 3.8+
- OpenCV(
opencv-python) - NumPy
实现代码
import cv2
import numpy as np
import glob
# 棋盘格内角点尺寸(内角点数 = 格子数 - 1)
CHECKERBOARD = (9, 6)
SQUARE_SIZE = 25.0 # 棋盘格每个格子的实际边长(单位:mm)
# 准备对象点(世界坐标系中棋盘格角点的三维坐标,z=0)
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
objpoints = [] # 所有图像对应的对象点
imgpoints = [] # 所有图像对应的像素角点
# 读取标定图像(请将图像文件放在当前目录的 calib_images/ 文件夹下)
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:
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('Corners', img)
cv2.waitKey(100)
else:
print(f'[跳过] 未检测到完整棋盘格: {fname}')
cv2.destroyAllWindows()
if len(objpoints) < 5:
raise RuntimeError('有效标定图像不足5张,请补充图像后重试')
# 执行相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
objpoints, imgpoints, gray.shape[::-1], None, None
)
# 输出标定结果
print('=== 相机内参标定结果 ===')
print('相机矩阵 (Camera Matrix):')
print(mtx)
print('\n畸变系数 (Distortion Coefficients):')
print(dist.ravel())
print(f'\n重投影误差 (RMS): {ret:.4f} 像素')
# 计算每张图像的平均重投影误差(可选验证)
total_error = 0
for i in range(len(objpoints)):
imgpoints_proj, _ = cv2.projectPoints(
objpoints[i], rvecs[i], tvecs[i], mtx, dist
)
error = cv2.norm(imgpoints[i], imgpoints_proj, cv2.NORM_L2) / len(imgpoints_proj)
total_error += error
print(f'平均每张图像重投影误差: {total_error / len(objpoints):.4f} 像素')
运行方式
- 准备标定板:打印一张9×6内角点的棋盘格(建议A4纸打印并贴在硬板上),测量每个格子的实际边长并填入
SQUARE_SIZE。 - 采集图像:从不同角度、距离、倾斜姿态拍摄棋盘格,确保棋盘格完整出现在画面中,共采集15~20张。将图像存入
calib_images/文件夹。 - 运行脚本:
python calibrate.py(将上述代码保存为calibrate.py)。
验证方法与通过标准
- 角点检测:运行过程中每张图像会显示检测到的棋盘格角点,若某张图像未检测到完整棋盘格,程序会跳过并提示。
- 标定成功标志:程序正常输出相机矩阵、畸变系数和RMS误差,且不报错。
- 质量判定:RMS重投影误差小于0.5像素为优秀,小于1.0像素为合格。若RMS大于1.0像素,应检查角点检测是否准确、剔除模糊图像、增加图像数量或改变拍摄角度后重新标定。
- 结果合理性:焦距(
mtx[0,0]和mtx[1,1])应与图像分辨率在同一量级(例如对1920×1080图像,焦距通常在1000~3000像素范围);主点(mtx[0,2],mtx[1,2])应接近图像中心。
常见问题
- 检测不到角点:确保棋盘格图像清晰、光照均匀、无强烈反光;避免棋盘格过小或过大占画面比例不当。
- 标定结果不稳定:图像数量不足或拍摄角度过于单一(如全部为正面拍摄)会导致结果不稳定,应保证图像覆盖画面各个区域并包含明显倾斜角度。
- 重投影误差偏大:检查
SQUARE_SIZE是否与实际打印尺寸一致(该值不影响RMS计算,但影响焦距的物理尺度);剔除角点检测明显偏移的图像。