【图像处理基石】什么是相机的内外参数?

发布于:2025-07-22 ⋅ 阅读:(13) ⋅ 点赞:(0)

在这里插入图片描述

相机内参与外参的概念

1. 相机内参(Intrinsic Parameters)

相机内参是描述相机自身光学和几何特性的参数,与拍摄场景无关,主要包括:

  • 焦距(fx,fyf_x, f_yfx,fy:镜头焦距在图像平面上的投影(单位:像素),分别对应x轴和y轴方向(通常因像素非正方形可能不同)。
  • 主点(cx,cyc_x, c_ycx,cy:光轴与图像平面的交点(单位:像素),理想情况下是图像中心。
  • 畸变系数:镜头光学畸变的参数,包括:
    • 径向畸变(k1,k2,k3k_1, k_2, k_3k1,k2,k3):因镜头形状导致的畸变(边缘像素偏移更明显)。
    • 切向畸变(p1,p2p_1, p_2p1,p2):因镜头与图像平面不平行导致的畸变。

内参矩阵通常表示为:
K=[fx0cx0fycy001] K = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} K= fx000fy0cxcy1

2. 相机外参(Extrinsic Parameters)

外参描述相机在世界坐标系中的位置和姿态,用于将世界坐标系中的3D点转换到相机坐标系,包括:

  • 旋转矩阵(RRR:3×3矩阵,描述相机坐标系相对世界坐标系的旋转。
  • 平移向量(ttt:3×1向量,描述相机坐标系原点相对世界坐标系原点的平移。

外参通过变换矩阵将世界坐标系点PwP_wPw转换为相机坐标系点PcP_cPc
Pc=R⋅Pw+t P_c = R \cdot P_w + t Pc=RPw+t

相机标定方法

相机标定的核心是通过已知的3D世界点及其对应的2D图像点,求解内参和外参。最常用的是张正友标定法,步骤如下:

  1. 准备平面标定板(如棋盘格),已知格子的物理尺寸(如20mm×20mm)。
  2. 从不同角度、姿态拍摄标定板的多张图片(通常需要10-20张)。
  3. 检测每张图片中棋盘格的内角点(2D图像坐标)。
  4. 定义内角点在世界坐标系中的3D坐标(例如,令标定板平面为Z=0Z=0Z=0,左上角为原点)。
  5. 利用透视变换约束,通过非线性优化求解内参、外参和畸变系数。

Python实现相机标定

使用OpenCV库实现标定,主要步骤:读取图片→检测角点→亚像素优化→标定计算→评估误差。

代码实现
import cv2
import numpy as np
import glob

# ---------------------- 配置参数 ----------------------
# 棋盘格内角点数量(行×列,不含边框)
chessboard_size = (9, 6)  # 例如:9列,6行内角点
# 棋盘格单个格子的物理尺寸(单位:mm)
square_size = 20.0

# 世界坐标系中的3D点(Z=0,仅X、Y有值)
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  # 缩放为实际物理尺寸

# 存储所有图片的3D世界点和2D图像点
obj_points = []  # 世界坐标系3D点
img_points = []  # 图像坐标系2D点

# ---------------------- 读取图片并检测角点 ----------------------
# 读取标定板图片(需提前准备,放在"calibration_images"文件夹)
images = glob.glob('calibration_images/*.jpg')  # 支持jpg/png等格式

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)  # 添加3D世界点
        
        # 亚像素角点优化(提高精度)
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
        corners_subpix = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
        img_points.append(corners_subpix)  # 添加优化后的2D图像点
        
        # 可视化角点检测结果
        img = cv2.drawChessboardCorners(img, chessboard_size, corners_subpix, ret)
        cv2.imshow('Chessboard Corners', img)
        cv2.waitKey(500)  # 每张图显示0.5秒

cv2.destroyAllWindows()

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

# ---------------------- 输出标定结果 ----------------------
print("标定是否成功:", "成功" if ret else "失败")
print("\n内参矩阵 K:\n", mtx)
print("\n畸变系数(k1, k2, p1, p2, k3):\n", dist)
print("\n外参(旋转向量和平移向量):")
for i in range(len(rvecs)):
    print(f"第{i+1}张图:")
    print(f"旋转向量 rvec:\n{rvecs[i]}")
    print(f"平移向量 tvec:\n{tvecs[i]}\n")

# ---------------------- 评估标定精度(重投影误差) ----------------------
# 重投影误差:标定后的3D点投影到图像上的位置与实际检测的2D点的偏差
mean_error = 0
for i in range(len(obj_points)):
    img_points2, _ = cv2.projectPoints(
        obj_points[i], rvecs[i], tvecs[i], mtx, dist
    )
    error = cv2.norm(img_points[i], img_points2, cv2.NORM_L2) / len(img_points2)
    mean_error += error

print(f"平均重投影误差:{mean_error / len(obj_points):.6f} 像素")
print("(误差越小,标定精度越高,通常应小于0.5像素)")

# ---------------------- 保存标定结果 ----------------------
np.savez('camera_calibration.npz', mtx=mtx, dist=dist, rvecs=rvecs, tvecs=tvecs)
print("\n标定结果已保存至 camera_calibration.npz")
测试用例说明
  1. 准备数据

    • 打印一张棋盘格标定板(如9×6内角点),测量单个格子的物理尺寸(如20mm)。
    • 用相机从不同角度、距离拍摄10-20张标定板图片(确保所有内角点都可见),保存到calibration_images文件夹。
  2. 运行代码

    • 安装依赖:pip install opencv-python numpy
    • 运行脚本,程序会自动检测角点并显示,最终输出内参、外参和重投影误差。
  3. 结果评估

    • 若平均重投影误差小于0.5像素,说明标定效果较好;若误差过大,需检查图片质量(如模糊、角点不全)或增加图片数量。

代码关键步骤解释

  1. 角点检测cv2.findChessboardCorners检测棋盘格内角点,返回粗略坐标。
  2. 亚像素优化cv2.cornerSubPix通过迭代提高角点坐标精度(至亚像素级别)。
  3. 标定核心cv2.calibrateCamera利用3D-2D点对应关系,求解内参(mtx)、畸变系数(dist)、外参(旋转向量rvecs、平移向量tvecs)。
  4. 精度评估:重投影误差反映标定参数的准确性,误差越小说明模型越可靠。

通过上述方法,可快速实现相机内外参的标定,为后续的立体视觉(如深度估计)、图像校正等任务奠定基础。