前面我们学完solvePnP 单目姿态估计,可以通过单张图片解算物体位姿、距离。
但单目视觉有一个致命短板:依赖已知物体尺寸,属于“推算距离”,不是真实测距。
想要机器真正像人眼一样直接看懂远近、自动生成场景深度,必须用到:双目立体视觉。
双目视觉的最终产物,就是深度图(视差图)。
在 OpenCV 中,生成深度图只用两大核心算法:
StereoBM(块匹配) & StereoSGBM(半全局块匹配)
一个极速轻量、一个高精度商用,覆盖了90%的双目测距场景。
今天带大家彻底吃透双目立体深度估计:立体视觉原理、视差与深度关系、两种算法区别、全套可运行代码、参数调优指南、工程落地避坑!
一、双目立体视觉核心原理(人话版)
人眼看物体之所以能分辨远近,是因为左右眼看到的画面存在位置偏差。
双目相机复刻了人眼视觉机制:
左右两个相机同时拍摄画面→ 匹配相同特征点 → 计算像素偏移量(视差)→ 换算真实物理深度
核心公式(必懂)
深度 Z = (焦距 f × 基线 B) / 视差 d
•基线B:左右相机光心距离
•焦距f:相机内参焦距
•视差d:同一点在左右图的像素偏移量
规律:视差越大、距离越近;视差越小、距离越远。
算法的核心工作,就是精准计算每一个像素的视差,生成整张图的视差深度图。
二、StereoBM 与 StereoSGBM 算法区别
1、StereoBM(Block Matching 块匹配)
最基础、最快速的立体匹配算法。
核心思路:以像素块为单位,在右图中滑动匹配左图像素块,相似度最高即为匹配点。
特点:
•计算量极小、速度极快、适合嵌入式实时运行
•纯局部匹配,只看小区域像素相似度
•弱纹理、平滑区域容易出现空洞、噪点
2、StereoSGBM(Semi-Global Block Matching 半全局匹配)
工业级高精度算法,是 StereoBM 的全面升级版,目前项目首选。
核心升级:不止局部块匹配,引入全局能量约束,兼顾相邻像素视差连续性。
特点:
•深度图极其平滑、空洞少、噪点极低
•适配弱纹理墙面、天空、路面等难匹配场景
•保留物体边缘轮廓精准
•速度略慢于BM,但依然满足实时工程需求
三、场景选型公式(直接抄作业)
•嵌入式设备、超低算力、实时视频测距→ StereoBM
•工业检测、三维重建、高精度测距、静态场景→ StereoSGBM(首选)
四、实战1:StereoBM 快速深度图生成
轻量极速版本,适合新手入门与低算力设备。
pythonimport cv2import numpy as np# 读取双目图像imgL = cv2.imread("left.jpg", 0)imgR = cv2.imread("right.jpg", 0)# 创建 StereoBM 对象# numDisparities:视差范围,必须16的倍数# blockSize:匹配块大小,奇数bm = cv2.StereoBM_create(numDisparities=96, blockSize=15)# 计算视差图disparity = bm.compute(imgL, imgR)# 归一化,转为可视化深度图disparity_norm = cv2.normalize(disparity, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)# 展示效果cv2.imshow("Left", imgL)cv2.imshow("BM Disparity", disparity_norm)cv2.waitKey(0)cv2.destroyAllWindows()# 保存结果cv2.imwrite("bm_depth.jpg", disparity_norm) |
五、实战2:StereoSGBM 工业高精度深度图(推荐)
工程最常用方案,参数更丰富、效果碾压BM,适配绝大多数双目项目。
pythonimport cv2import numpy as npimgL = cv2.imread("left.jpg")imgR = cv2.imread("right.jpg")# 转为灰度图grayL = cv2.cvtColor(imgL, cv2.COLOR_BGR2GRAY)grayR = cv2.cvtColor(imgR, cv2.COLOR_BGR2GRAY)# 创建SGBM匹配器sgbm = cv2.StereoSGBM_create(minDisparity=0,numDisparities=96, # 视差搜索范围blockSize=9, # 匹配块大小P1=8 * 3 * 9 ** 2, # 平滑约束系数1P2=32 * 3 * 9 ** 2, # 平滑约束系数2disp12MaxDiff=1,uniquenessRatio=10,speckleWindowSize=100,speckleRange=2)# 计算视差图disparity = sgbm.compute(grayL, grayR)# 归一化可视化disparity_norm = cv2.normalize(disparity, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)# 彩色深度图,观感更佳disparity_color = cv2.applyColorMap(disparity_norm, cv2.COLORMAP_JET)cv2.imshow("Left", imgL)cv2.imshow("SGBM Depth Gray", disparity_norm)cv2.imshow("SGBM Depth Color", disparity_color)cv2.waitKey(0)cv2.destroyAllWindows()cv2.imwrite("sgbm_depth_color.jpg", disparity_color) |
六、核心参数调优指南(工程必看)
•numDisparities 视差范围:必须是16的整数倍,场景越深、测距越远,取值越大
•blockSize 匹配块:纹理复杂用小尺寸,平滑无纹理区域用大尺寸
•P1/P2 平滑系数:P2>P1,数值越大深度图越平滑,但细节越模糊
•speckle 斑点滤波:去除深度图小白噪点、空洞碎块
七、BM与SGBM优缺点终极对比
StereoBM
✅ 优点:算法简单、速度最快、资源占用极低、适合嵌入式实时推理
❌ 缺点:弱纹理区域失效严重、噪点多、空洞多、边缘粗糙
StereoSGBM
✅ 优点:全局约束、深度连续、空洞少、抗干扰强、边缘精准、工业可用
❌ 缺点:参数较多、速度略慢于BM
八、新手高频避坑指南
•坑1:未做双目校正直接匹配双目图像必须先经过双目标定+极线校正,否则左右像素不平行,匹配完全错乱
•坑2:numDisparities 不是16倍数参数不规范,直接导致无深度、全黑画面
•坑3:视差范围设置过小物体远近超出搜索范围,出现大面积空洞
•坑4:直接使用原始视差图测距原始视差为定点数值,必须归一化、映射后再代入公式计算真实距离
•坑5:弱纹理场景用BM墙面、天空、路面几乎匹配不到点,深度图全黑,必须用SGBM
九、全文总结
双目深度估计,是传统视觉实现“真实三维感知”的最后一块拼图。
如果说单目PnP是“推算位姿”,双目SGBM/BM就是“直接看懂深度”。
两套算法定位清晰:
轻量化实时场景→ StereoBM
高精度三维重建、测距检测→ StereoSGBM(首选)
掌握双目深度图生成,你就具备了二维图像转向三维空间感知的完整能力!
❤️ 点赞+在看,后台回复关键词【双目深度】,领取双目校正+深度测距完整工程代码+参数调优对照表!
关注【AI与计算机视觉】,持续更新 OpenCV 立体视觉、三维重建高阶实战!
评论区打卡:立体深度,一起进阶三维机器视觉!