未标定相机下运行stereoRectifyUncalibrated后如何获取Q矩阵?
未标定相机下构建Q矩阵的方法
首先明确:未标定场景下无法直接得到带真实尺度的绝对深度,只能先得到相对深度,再通过已知尺寸物体校准尺度。以下是具体实现步骤:
核心原理
Q矩阵是4×4投影矩阵,作用是将校正后的视差图转换为3D点云,其核心依赖校正后相机的主点(cx, cy)、焦距f、左右相机基线B三个参数。未标定情况下,我们可以通过经验值或校正结果近似构建Q矩阵。
方法一:手动构建相对Q矩阵(最简单实用)
因为stereoRectifyUncalibrated已经将左右图像校正到极线水平对齐状态,此时视差仅在X方向,直接按以下规则构建Q矩阵:
- 主点(cx, cy):设为图像中心,即
cx = 图像宽度/2,cy = 图像高度/2 - 焦距f:用图像的最大边长作为经验值(比如640×480的图像设f=640),后续可通过已知物体校准
- 基线B:如果能测量左右相机光心的实际距离(比如用尺子量)就填真实值;无法测量则设为1,得到的深度为相对值,之后再缩放
代码示例(OpenCV-Python)
import cv2 import numpy as np # 校正后的图像尺寸 img_width = 640 img_height = 480 # 设定参数 cx = img_width / 2.0 cy = img_height / 2.0 f = img_width # 经验焦距 baseline = 0.1 # 真实基线(单位:米,无法测量就设为1) # 构建Q矩阵 Q = np.float32([ [1, 0, 0, -cx], [0, 1, 0, -cy], [0, 0, 0, f], [0, 0, -1/baseline, 0] # 校正后左右主点X坐标一致,故最后一项为0 ]) # 转换视差图为3D点云 disparity_map = cv2.imread('your_disparity.png', cv2.IMREAD_GRAYSCALE) # 视差图建议先做去噪/空洞填补,比如用cv2.filterSpeckles或cv2.inpaint points_3d = cv2.reprojectImageTo3D(disparity_map, Q)
方法二:从stereoRectifyUncalibrated的单应矩阵推导(进阶)
stereoRectifyUncalibrated输出的H1、H2是左右图像到校正平面的单应矩阵,可通过它们推导校正后的相机内参:
- 从H1中分解出旋转和缩放因子,近似得到焦距f
- 结合极线平行的约束,确定平移向量(基线相关)
但该方法计算复杂,且未标定情况下仍无法得到绝对尺度,仅适合追求相对精度更高的场景,一般推荐用方法一。
关键注意事项
- 视差图必须是校正后的结果(即经过stereoRectifyUncalibrated映射后的图像计算的视差),否则Q矩阵无效
- 若要得到真实深度,需用场景中已知尺寸的物体校准:比如已知某物体真实高度为h,图像中像素高度为h_pix,真实深度为Z_real,则真实焦距
f_real = (h_pix * Z_real) / h,替换Q矩阵中的f即可 - 视差图预处理很重要,建议先用
cv2.filterSpeckles去除噪声,再用cv2.inpaint填补空洞
内容的提问来源于stack exchange,提问作者ajeelahmed1998
相关产品推荐
相关产品推荐

