如何利用Rectification拼接足球场相邻两台相机的视图?
利用相机中心线向量与间距实现足球场双相机画面校正拼接
核心前提确认
首先必须明确:仅靠中心线夹角和相机间距(外参)不足以完成校正,你必须先完成相机内参标定——获取两台相机的内参矩阵(焦距、主点)和畸变系数。之前出现彩色条纹,大概率是跳过了内参标定,或者外参的坐标系没统一导致参数错误。
步骤1:构建相机外参矩阵
以其中一台相机为基准坐标系(比如相机1的光心为原点,中心线为Z轴):
- 平移向量T:根据相机间距,直接写出相机2光心相对于相机1的坐标(比如相邻部署在X轴方向,间距为d,则T=(d, 0, 0),单位用物理单位如米)。
- 旋转矩阵R:根据两台相机的中心线向量夹角θ,用罗德里格斯公式计算旋转矩阵——先求两个中心线向量的叉乘得到旋转轴,再结合夹角θ生成将相机1的Z轴转到相机2中心线方向的正交旋转矩阵。
步骤2:用OpenCV执行校正(示例代码)
假设你已经完成内参标定,得到K1/K2(内参矩阵)、dist1/dist2(畸变系数),图像尺寸为img_size:
import cv2 import numpy as np # 输入已知参数:R是相机2相对相机1的旋转矩阵,T是平移向量 R1, R2, P1, P2, Q, _, _ = cv2.stereoRectify(K1, dist1, K2, dist2, img_size, R, T) # 生成重映射表 map1x, map1y = cv2.initUndistortRectifyMap(K1, dist1, R1, P1, img_size, cv2.CV_32FC1) map2x, map2y = cv2.initUndistortRectifyMap(K2, dist2, R2, P2, img_size, cv2.CV_32FC1) # 对图像做校正 rect_img1 = cv2.remap(img1, map1x, map1y, cv2.INTER_LINEAR) rect_img2 = cv2.remap(img2, map2x, map2y, cv2.INTER_LINEAR)
校正后的两张图像会处于同一平面,对应行的像素对应空间中同一点,之后直接用cv2.hconcat或特征匹配拼接即可得到连贯的全景画面。
彩色条纹问题排查
- 内参错误:如果没做标定,用默认内参矩阵会导致投影完全错误,必须用棋盘格等工具完成内参标定,消除镜头畸变。
- 外参坐标系混乱:确保中心线向量是在同一坐标系下计算的夹角,比如都以相机1的坐标系为基准,否则旋转矩阵R会完全失效。
- 平移向量单位不匹配:平移向量的物理单位要和内参的标定单位一致(比如内参标定时用米,T也用米),否则会出现比例失调。
- 图像尺寸不一致:两张输入图像的分辨率必须完全相同,否则重映射时会出现错位条纹。
替代方案:平面投影拼接
如果立体校正仍有问题,可以直接将两张图像投影到足球场平面(比如草地):
根据相机外参和平面方程(假设草地为世界坐标系Z=0平面),计算单应性矩阵H:
# H = K2 * (R - T @ n.T / d) * np.linalg.inv(K1) # n是平面法向量(Z=0平面的n=(0,0,1)),d是平面到原点的距离(这里d=0) H = K2 @ (R - T @ np.array([0,0,1]).reshape(3,1)/0) @ np.linalg.inv(K1) # 投影图像 warped_img2 = cv2.warpPerspective(img2, H, (img_width_total, img_height))
将两张图像投影到同一平面后,再做拼接即可得到类似目标的侧视图/全景图。
内容的提问来源于stack exchange,提问作者Kyle Cooke
相关产品推荐
相关产品推荐

