基于OpenCV Python计算立体系统深度图(已知相机参数)
用OpenCV从双目相机参数计算深度图的方法
核心逻辑
OpenCV没有直接跳过视差图生成深度图的函数,必须先通过立体匹配得到视差图,再结合相机参数将视差转换为深度信息。
具体实现步骤
1. 立体校正(若图像未校正)
如果左右图像还没经过立体校正,先利用已知的内参、外参计算校正映射并处理图像:
import cv2 import numpy as np # 输入已知参数:内参K1/K2、畸变系数dist1/dist2、旋转矩阵R、平移向量T、图像尺寸 R1, R2, P1, P2, Q, _, _ = cv2.stereoRectify(K1, dist1, K2, dist2, img_left.shape[:2], R, T) map1_l, map2_l = cv2.initUndistortRectifyMap(K1, dist1, R1, P1, img_left.shape[:2], cv2.CV_32FC1) map1_r, map2_r = cv2.initUndistortRectifyMap(K2, dist2, R2, P2, img_right.shape[:2], cv2.CV_32FC1) # 得到校正后的左右图像 rectified_left = cv2.remap(img_left, map1_l, map2_l, cv2.INTER_LINEAR) rectified_right = cv2.remap(img_right, map1_r, map2_r, cv2.INTER_LINEAR)
2. 立体匹配生成视差图
推荐用SGBM算法(比基础BM算法精度更高):
# 初始化SGBM匹配器 sgbm = cv2.StereoSGBM_create( minDisparity=0, numDisparities=80, # 必须是16的倍数,根据实际场景调整 blockSize=5, P1=8*3*5**2, P2=32*3*5**2, disp12MaxDiff=1, uniquenessRatio=10, speckleWindowSize=100, speckleRange=32 ) # 计算视差并转换为真实值 disparity = sgbm.compute(rectified_left, rectified_right) disparity = disparity.astype(np.float32) / 16.0
3. 从视差图生成深度图
利用cv2.reprojectImageTo3D()结合stereoRectify输出的Q矩阵,将视差转换为包含深度的3D点云,再提取深度通道:
# 生成3D点云,每个像素对应(x,y,z),z即为深度 points_3d = cv2.reprojectImageTo3D(disparity, Q) # 提取深度图 depth_map = points_3d[:, :, 2] # 过滤无效深度值(视差为0的区域) depth_map[disparity <= 0] = np.nan
关键说明
Q矩阵是由相机内参、外参计算得到的核心转换矩阵,必须使用stereoRectify输出的结果,不能手动构造- 深度图的单位与你输入的外参平移向量单位一致(比如平移单位是米,深度单位就是米)
- 若图像已完成立体校正,可跳过第一步,直接使用已知的
Q矩阵进行转换
内容的提问来源于stack exchange,提问作者CVDE
相关产品推荐
相关产品推荐

