Python双目立体视觉测距实战:从相机标定到SGBM实时测距

发布时间:2026/8/31 19:43:29
Python双目立体视觉测距实战:从相机标定到SGBM实时测距 简介本资源是一套基于Python实现的双目立体视觉测距系统源码面向计算机视觉初学者、机器学习实践者及嵌入式视觉应用开发者聚焦解决真实场景下双目测距精度受光照变化、纹理缺失与基线限制等关键问题。压缩包共6个文件79KB含核心算法脚本stereo_vision.py、标定用棋盘格图像9x6_1-8cm_chessboard.png、项目说明文档README.md、开源许可证LICENSE及备份文件结构精简便于快速部署与原理验证。已有39人学习下载适合在受限算力环境下开展立体匹配、视差图生成与深度距离换算等基础实验。读者可直接运行主程序理解极线校正、SGBM匹配、视差转深度全流程结合文档掌握光照鲁棒性调优思路与纹理增强的工程应对逻辑是入门双目视觉测距不可多得的轻量级实践样本。0. 为什么我折腾了这套双目测距系统如果你搜过“双目测距”“深度相机”这类关键词大概率会看到一堆卖方案的公司、漫天飞的广告。但真正想自己动手做一套用普通USB摄像头实现测距、并且把代码跑通的人往往要踩不少坑。这篇文章就是记录我完整实现一套Python双目立体视觉测距系统的全过程——从硬件选型、相机标定、立体匹配到最终输出三维坐标和距离全部源码可复现。这套系统能做什么简单说就是两个普通摄像头模拟人眼通过视差计算出画面中任意目标点到相机的距离。它适合机器人避障、物流分拣、AR交互、监控安防这些场景。如果你有一块英伟达开发板或者一台普通电脑预算一百块以内就能开始比买深度相机便宜太多。适合谁看准备入门立体视觉的学生、做毕设的本科生、想把测距能力加进自己项目的工程师。我尽量把每个环节讲清楚包括“为什么要这么做”以及“我踩过的坑”。1. 整体设计与思路拆解为什么选用Python和普通双目摄像头1.1 双目测距到底解决了什么问题先从底层需求说起。日常做视觉测量单目相机很难直接获得深度信息——一张照片里一个物体近还是远单靠像素位置根本算不出来。如果只用运动恢复结构SFM或者深度学习单目深度估计对算力要求高而且绝对精度一般。双目立体视觉的思路是用两个已知相对位姿的相机同时拍摄通过匹配左右图片中同一个物理点的像素位置差视差结合基线长度和镜头焦距解算出该点相对于相机的三维坐标。这个方案的天然优势是不需要主动光源、不依赖额外硬件深度传感器只靠两个普通RGB相机就能获得稠密或稀疏的深度信息。在室内、室外有一定纹理的环境下精度和实时性都能做到不错的平衡。1.2 为什么选Python而不是C如果你搜开源的双目项目会发现C版本居多比如OpenCV自带的stereo_match.cpp例子。但Python版本并不少OpenCV-Python包把标定、校正、匹配、三维重建的接口全部暴露出来了效率足够学习和小型项目使用代码比C短得多。对于前期验证算法、快速迭代来说Python是第一选择。后期需要部署到嵌入式设备再用C重写核心链路也不迟。我在设计这套系统时的技术栈是Python 3.8OpenCV 4.x含opencv-contrib-pythonNumPy两个普通USB摄像头或一个双目摄像头模组1.3 整体流程与模块划分整套测距系统分为四个模块图像采集与校正、立体匹配、三维重建、测距输出。图像采集模块负责从两个摄像头同步获取左右图像并完成畸变校正和极线校正。立体匹配模块负责计算视差图这是整个系统的核心也是最容易出问题的地方。三维重建模块把视差图转化为三维点云测距输出模块则从三维坐标中提取目标距离。这个流程几乎是所有双目系统的标准范式从ROS的stereo_image_proc到工业视觉软件都是这个思路。理解了它你就理解了双目测距的骨架。2. 核心原理拆解视差、基线与深度的关系2.1 用“手指实验”理解视差小时候我们都做过一个实验闭上一只眼伸出食指放在眼前换另一只眼看会发现手指相对于背景发生了明显的移动。这就是视差。双目相机模仿的就是这个原理。想象两个摄像头水平放置距离为B基线。空间中的一点P在左相机成像位置为x_left在右相机成像位置为x_right。如果两个相机光轴平行、焦距相同那么x_left和x_right的差值就是视差d。公式非常简单也是最核心的公式Z (f * B) / d其中Z是目标点到相机平面的距离f是焦距像素单位B是基线长度d是视差。这个公式解释了为什么基线越长测距范围越大、精度越高也解释了为什么近处物体视差大远处物体视差几乎为0。2.2 为什么必须做极线校正实际安装两个摄像头时很难做到完美平行。哪怕只有一度偏差同一个点在左右图中的匹配搜索范围就会变成二维计算量剧增、误匹配率飙升。解决办法是极线校正通过标定得到的旋转矩阵和平移向量对左右图像各做一次重投影让两个图像平面共面且行对齐。校正之后同一个物理点的左右图像坐标只在同一行上移动匹配搜索从二维退化到一维效率和准确率大幅提升。这也是很多新手容易忽略的一步——拿着两个摄像头直接跑SGBM结果视差图一团糟就是因为没有做极线校正。2.3 相机标定决定了测距精度的上限整套系统中标定是最枯燥、最容易被跳过、也最影响精度的环节。标定需要得到以下参数左右相机各自的内参矩阵fx, fy, cx, cy和畸变系数k1, k2, p1, p2, k3左右相机之间的旋转矩阵和平移向量本征矩阵和基础矩阵用于极线校正我用的标定方法是经典的棋盘格标定法OpenCV的findChessboardCorners加calibrateCamera接口可以完成单目标定stereoCalibrate完成双目标定。建议单目先标再把结果传给双目标定这样收敛更快。3. 相机标定与图像校正实操3.1 准备工作摄像头和标定板怎么选先解决硬件问题。我最初用的是两个独立的USB摄像头这有一个隐患两个摄像头无法硬件同步抓拍运动物体时左右图有时间差导致视差匹配不准确。如果做静态测距或者慢速场景这个问题不严重如果做高速运动目标测距建议购买同步双目的模组淘宝上几十块钱就能买到双镜头模组内部已经用硬件做一个同步触发。标定板方面我用的是A4纸打印的棋盘格格数为9x6格边长为25mm。注意打印后要实际测量格子的边长不要相信打印设置的标称值打印机的缩放误差会直接影响测距精度。3.2 拍摄标定图的注意事项踩坑实录拍摄标定图片是最容易翻车的步骤。第一图片数量不要少于20对我实际拍了30对保证覆盖画面各个区域。特别是画面边缘和角落必须要覆盖到否则边缘畸变参数标不准。第二标定板在画面中的姿态要丰富倾斜、旋转、远近变化都要拍。不要只拍正面正对着镜头的图那样解算出的内参病态。第三注意对焦和光照。标定板的角点检测对清晰度要求很高模糊图片会让角点坐标偏移零点几个像素累积下来对内参影响很大。第四我踩过最坑的一件事反光。塑封过的标定板在强光下会产生高光导致角点检测失败。解决方案是打哑光的横幅材质标定板或者用喷墨打印在无光铜版纸上。拍摄完成后把所有的左右图像对按顺序命名存放在两个文件夹里left和right然后用下面这段代码找角点并剔除不合格的图片。import cv2 import numpy as np CHECKERBOARD (9, 6) criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) objp np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32) objp[:, :2] np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2) left_images [] right_images [] objpoints [] for i in range(30): left_path fcalib/left_{i}.jpg right_path fcalib/right_{i}.jpg left_img cv2.imread(left_path) right_img cv2.imread(right_path) left_gray cv2.cvtColor(left_img, cv2.COLOR_BGR2GRAY) right_gray cv2.cvtColor(right_img, cv2.COLOR_BGR2GRAY) ret_l, corners_l cv2.findChessboardCorners(left_gray, CHECKERBOARD, None) ret_r, corners_r cv2.findChessboardCorners(right_gray, CHECKERBOARD, None) if ret_l and ret_r: corners_l cv2.cornerSubPix(left_gray, corners_l, (11, 11), (-1, -1), criteria) corners_r cv2.cornerSubPix(right_gray, corners_r, (11, 11), (-1, -1), criteria) objpoints.append(objp) left_images.append(corners_l) right_images.append(corners_r) else: print(f第 {i} 对图片未能完整检测已丢弃)3.3 单目标定和双目标定的全流程代码先做左右相机各自的标定获得内参和畸变系数再做双目联合标定获得两个相机之间的外参。下面是一段可以直接跑通的标定代码。# 单目标定只列左相机部分右相机同理 ret_l, mtx_l, dist_l, rvecs_l, tvecs_l cv2.calibrateCamera( objpoints, left_images, left_gray.shape[::-1], None, None ) ret_r, mtx_r, dist_r, rvecs_r, tvecs_r cv2.calibrateCamera( objpoints, right_images, right_gray.shape[::-1], None, None ) # 双目标定 flags cv2.CALIB_FIX_INTRINSIC criteria_stereo (cv2.TERM_CRITERIA_MAX_ITER cv2.TERM_CRITERIA_EPS, 100, 1e-5) ret_stereo, mtx_l, dist_l, mtx_r, dist_r, R, T, E, F cv2.stereoCalibrate( objpoints, left_images, right_images, mtx_l, dist_l, mtx_r, dist_r, left_gray.shape[::-1], criteriacriteria_stereo, flagsflags )标记一下上面代码里双目标定采用的flag是CALIB_FIX_INTRINSIC意思是单目已经标定得很好了双目标定只优化外参R和T。这是常用做法避免优化参数太多导致过拟合。3.4 极线校正和重映射得到R和T之后用stereoRectify计算左右相机的校正映射矩阵然后用initUndistortRectifyMap生成查找表最后用remap把图像校正到理想的共面行对齐状态。R1, R2, P1, P2, Q, validPixROI1, validPixROI2 cv2.stereoRectify( mtx_l, dist_l, mtx_r, dist_r, left_gray.shape[::-1], R, T, alpha0 ) map1_l, map2_l cv2.initUndistortRectifyMap( mtx_l, dist_l, R1, P1, left_gray.shape[::-1], cv2.CV_32FC1 ) map1_r, map2_r cv2.initUndistortRectifyMap( mtx_r, dist_r, R2, P2, left_gray.shape[::-1], cv2.CV_32FC1 ) rectified_left cv2.remap(left_img, map1_l, map2_l, cv2.INTER_LINEAR) rectified_right cv2.remap(right_img, map1_r, map2_r, cv2.INTER_LINEAR)验证校正效果有一个技巧在两张校正后的图上画几条水平线然后拼接在一起看如果左右图同一物体落在同一条水平线上说明校正质量合格。我当时画了三条水平线一一眼看过去基本对齐才进入下一步。这一步如果没做好后面所有匹配都是白费。4. 立体匹配SGBM算子与视差图后处理4.1 为什么选SGBM而不是BM或深度学习立体匹配算法从传统的块匹配BM、半全局匹配SGBM到现在的深度学习匹配网络各有优劣。BM算法速度最快但视差图往往很破碎SGBM在速度和精度之间取得了一个很好的平衡尤其对中等纹理场景效果很好深度学习方案精度最高但需要GPU、需要数据集。我的项目目标是普通电脑上能够实时运行所以选了SGBM。OpenCV的StereoSGBM_create接口开箱即用。SGBM的原理简单说把二维匹配问题转化为一维路径聚合问题从多个方向扫描代价然后求累计代价最小的视差值。它比BM多考虑了像素邻域的信息让视差图在纹理缺失区域依然保持平滑。4.2 SGBM参数整定的血泪经验以下参数是SGBM效果好坏的关键每个我都实测调过。minDisparity最小视差值如果是校正后的近距离场景一般设0。numDisparities最大视差减最小视差必须是16的倍数。这和焦距、基线、最近测距距离有关。比如基线60mm、焦距800像素想测最近0.5米那么最大视差约96numDisparities设为96或112比较合适。blockSize匹配窗口大小奇数。窗口越大视差图越平滑但边缘细节会丢失我最终选的7。P1和P2平滑惩罚参数控制视差变化剧烈程度。P1的典型值是8 * blockSize * blockSizeP2是32 * blockSize * blockSize。P2太小会让视差图噪声大太大又会把深度边缘磨平。disp12MaxDiff左右一致性检查的最大差值设为1可以滤掉大部分误匹配。uniquenessRatio最低匹配代价需要比其他候选代价小多少比例设5到15。设太小则误匹配多设太大则有效视差点变少。speckleWindowSize和speckleRange去除连通域面积小于阈值的斑点speckleWindowSize设为100speckleRange设为2。我最终的SGBM参数如下import cv2 def create_sgbm(): return cv2.StereoSGBM_create( minDisparity0, numDisparities96, blockSize7, P18 * 7 * 7, P232 * 7 * 7, disp12MaxDiff1, uniquenessRatio10, speckleWindowSize100, speckleRange2, modecv2.STEREO_SGBM_MODE_SGBM ) sgbm create_sgbm() disparity sgbm.compute(rectified_left_gray, rectified_right_gray).astype(np.float32) / 16.0注意OpenCV输出的原始视差是定点数要除以16才是真实像素视差值这个细节很容易被忽略新手经常忘记除16导致算出来的距离差了16倍。4.3 视差图后处理提升匹配质量SGBM输出的视差图通常带噪声直接用来测距会得到跳变的结果。我做了三步后处理用cv2.medianBlur对空洞区域填充并去噪。对极远的无效视差比如视差值小于某个阈值直接置0。因为超过有效测距范围后视差噪声占比太高不如不要。用形态学闭运算填补小黑洞。我实际使用时发现加一个双边滤波或引导滤波视差图的边缘保持效果更好。OpenCV里没有内置引导滤波但可以用cv2.ximgproc里的fastGlobalSmootherFilter效果也不错不过对实时性有影响。disp_masked cv2.medianBlur(disparity, 5) disp_masked[disp_masked 2] 04.4 纹理缺失和遮挡是匹配失败的两大主因如果你的场景是白墙、纯色地面SGBM在那些区域基本得不到有效视差。这不是参数问题是算法本身的待改善点。实际工程中常用办法是给场景增加纹理比如贴标记物或者用结构光做一个随机斑点投影。遮挡是另一个问题左图中可见的目标点在右图中可能被前景物体挡住这样就不存在正确的匹配。所以左右一致性检查很重要它会把这些遮挡点标记为无效。5. 三维重建与测距函数封装5.1 用Q矩阵把视差图转成三维点云在stereoRectify阶段除了得到校正映射矩阵还会输出一个4x4的Q矩阵它的作用是把视差图转为三维坐标。Q * [x, y, disparity(x,y), 1]^T [X, Y, Z, W]实际三维坐标为 (X/W, Y/W, Z/W)。OpenCV提供了一个封装好的函数来完成这个转换points_3d cv2.reprojectImageTo3D(disp_masked, Q, handleMissingValuesTrue)得到的points_3d是一个与图像同尺寸的矩阵每个像素位置存放该点的三维坐标(X, Y, Z)。注意Z值就是该点到相机平面的距离。5.2 测距函数框选目标就输出距离在拿到三维点云后测距就变成一个取平均值的问题。我封装了一个函数给定左图中的一个矩形框比如通过yolo检测目标得到的框提取框中心区域的像素对应的三维点去掉无效点和离群点取Z的中位数作为测距结果。取中位数而不是平均值的原因是SGBM的视差在边缘区域噪声大偶尔会有几个极大的离群值平均值会被这些离群点拉偏中位数更稳定。import numpy as np def measure_distance_from_region(points_3d, bbox): bbox: (x_min, y_min, x_max, y_max) points_3d: HxWx3 的三维点云 x_min, y_min, x_max, y_max bbox region points_3d[y_min:y_max, x_min:x_max, :] z_values region[:, :, 2].flatten() z_valid z_values[np.isfinite(z_values) (z_values 0)] if len(z_valid) 10: return -1.0 z_median np.median(z_valid) # 用MAD过滤离群值 mad np.median(np.abs(z_valid - z_median)) z_filtered z_valid[np.abs(z_valid - z_median) 3 * mad] if len(z_filtered) 5: return -1.0 return float(np.median(z_filtered))注意框选区域一定要适当内缩。如果把目标的整个外接矩形用来测距矩形边缘会包含大量背景点导致测距结果偏到背景上去。实战中我通常把矩形向内收缩20%再取点。5.3 测距精度测试不同距离下的误差情况我把双目相机固定好用卷尺拉出几个已知距离分别测1米、2米、3米、5米每组测了50次取平均。测试结果如下真实距离米实测距离米绝对误差厘米1.01.0222.02.0553.03.10105.05.2525可以看出距离越远误差越大误差基本随距离的平方增长。这是因为视差是离散的远处的视差很小一个像素的量化误差会导致很大的深度误差。这个规律是所有被动视觉测距系统的天花板不是算法不好是硬件分辨率和基线长度决定的。要提升远距离精度最直接的办法就是增大基线、提高图像分辨率。基线从6cm加到12cm相同距离下精度几乎翻倍。6. 工程化部署实时视频流测距与性能优化6.1 从静态图像到实时视频流做视频流测距思路和静态图像完全一致只是要多一个循环读取摄像头帧、校正、算视差、测距、显示。这里有一个必须注意的问题两个USB摄像头打开后很难做到精确同步。即使同时调用了cap.read()两个摄像头内部帧率、自动曝光、白平衡完全独立出来的图像帧时间戳不一致轻微运动都会造成视差错误。我的解决办法是在初始化阶段关闭自动曝光、自动白平衡、自动对焦统一手动设置曝光时间和白平衡。在循环里加入同步等待逻辑不要求逐帧同步只要两边的图像时间差足够小就行。如果对实时性没硬性要求取两帧进行时间戳对齐后再计算。如果你用的是支持硬件同步的双目模组这部分可以省心很多。6.2 性能优化多线程和缓存SGBM的计算很耗时尤其在大分辨率下。我用640x480分辨率时SGBM耗时大概40毫秒加上校正和重建整体勉强到15帧。如果要做更流畅的实时有以下几个优化方向把校正的remap lookup table提前算好存储在内存里不要在每一帧重复计算。用cv2.getTickCount做耗时统计分析找出瓶颈在哪个模块。只对ROI区域做立体匹配不需要全图视差时可以裁剪左右图的重叠区域来减少计算量。用OpenCV的UMat或者CUDA版本把SGBM放到GPU上跑。CUDA版的cv2.cuda_StereoSGBM在GTX 1060上处理640x480图像可以跑到10毫秒以内。利用多线程分别采集左右摄像头主线程只负责计算。但注意GIL的存在纯粹的Python开多线程并不能加速计算密集型任务要用进程或者把耗时任务放到C扩展里。下面是我优化后的实时主循环骨架import cv2 import numpy as np cap_left cv2.VideoCapture(0) cap_right cv2.VideoCapture(1) # 关闭自动参数手动设置 for cap in (cap_left, cap_right): cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25) cap.set(cv2.CAP_PROP_EXPOSURE, 100) cap.set(cv2.CAP_PROP_AUTO_WB, 0) cap.set(cv2.CAP_PROP_GAIN, 0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) sgbm create_sgbm() while True: ret_l, frame_l cap_left.read() ret_r, frame_r cap_right.read() if not ret_l or not ret_r: continue gray_l cv2.cvtColor(frame_l, cv2.COLOR_BGR2GRAY) gray_r cv2.cvtColor(frame_r, cv2.COLOR_BGR2GRAY) rect_l cv2.remap(gray_l, map1_l, map2_l, cv2.INTER_LINEAR) rect_r cv2.remap(gray_r, map1_r, map2_r, cv2.INTER_LINEAR) disp sgbm.compute(rect_l, rect_r).astype(np.float32) / 16.0 disp[disp 2] 0 points_3d cv2.reprojectImageTo3D(disp, Q) # 这里可以接你的目标检测框然后调用 measure_distance_from_region # bbox detector(frame_l) # distance measure_distance_from_region(points_3d, bbox) cv2.imshow(left, frame_l) cv2.imshow(disparity, (disp / 96.0 * 255).astype(np.uint8)) if cv2.waitKey(1) 0xFF ord(q): break cap_left.release() cap_right.release() cv2.destroyAllWindows()6.3 光照、纹理、遮挡三大实战杀手我必须明确告诉你这套系统在理想条件下表现不错但在真实环境中很容易翻车。光照变化是第一个杀手。左右两个摄像头如果受到光照角度不一致同一个表面的亮度不相同匹配代价就会偏大导致该区域视差无效。解决办法是使用gamma校正或者对图像做归一化处理我在实测时做了一步简单的直方图均衡对光照不均有所改善。低纹理区域是第二个杀手。白墙、纯色地面、天空这些区域SGBM基本无能为力。如果你要测距的目标恰好没纹理可以考虑加贴纸或结构光。遮挡是第三个杀手。两个摄像头视角不同必然存在遮挡区域。目标边缘和前后景交界处视差图容易出现空洞或错误的深度跳跃。这部分只能用滤波和小孔填充来修补做不到完美。我做目标检测加测距时最稳的方案是用目标检测框锁定目标中心区域中心区域通常遮挡较少、纹理相对丰富测距结果最可靠。不要用整个框的像素去测距。6.4 参数速查表与调试建议模块常用参数/工具推荐值/建议标定棋盘格尺寸9x6格边长实测标定图片数量30对以上覆盖边缘和姿态SGBMnumDisparities96~128SGBMblockSize5~11取奇数SGBMP1 / P28bsbs / 32bsbsSGBMdisp12MaxDiff1SGBMuniquenessRatio10深度转换disp / 16.0必须做后处理medianBlur5x5三维重建reprojectImageTo3D用Q矩阵调试的时候第一步先看视差图是否连续、边缘是否清晰。视差图就是整个测距系统的心电图心电图上出了问题后面算出的距离必然不可信。如果视差图边缘有“光晕”说明P2太小如果视差图中大量空洞说明uniquenessRatio或disp12MaxDiff设置过严或者光照条件不佳如果视差图有横向水平条带说明图像校正没做好回去检查stereoRectify的参数。7. 项目源码结构与后续扩展方向7.1 源码目录与核心文件为了让整套源码更易维护我把项目拆成了几个文件stereo_depth/ ├── calibration/ │ ├── capture_calib_images.py # 采集标定图片 │ ├── calibrate.py # 单目和双目标定 │ └── calibration_params.npz # 保存的标定参数 ├── stereo/ │ ├── stereo_matcher.py # SGBM匹配器配置 │ ├── rectifier.py # 校正模块 │ └── depth_engine.py # 三维重建与测距封装 ├── tools/ │ ├── measure_point.py # 点击图像任意点测距 │ ├── measure_bbox.py # 目标框测距 │ └── live_demo.py # 实时视频流测距demo └── README.md标定参数我用np.savez保存为npz文件运行时直接加载不需要每次标定。这里提醒一下标定参数只对固定的相机位置和焦距有效。如果你的相机焦距变了比如自动对焦被重新打开必须重新标定。7.2 点击图像任意点测距的小工具这个工具非常实用在图像上点击任意一个点立刻显示该点的三维坐标和距离。它本质上就是取三维点云中对应像素的坐标值。我在日常调试中几乎天天用。def on_mouse(event, x, y, flags, param): if event cv2.EVENT_LBUTTONDOWN: X, Y, Z points_3d[y, x] print(f像素({x}, {y}) - 三维坐标({X:.2f}, {Y:.2f}, {Z:.2f}) 距离 {Z:.2f} 米)7.3 可以怎么继续扩展如果这套系统你已经跑通了后续有几个方向可以考虑与目标检测结合用YOLO检测目标输出的bbox加上收缩策略输入测距函数变成一个完整的单目检测加双目测距模块。这也是目前很多机器人项目的需求。视觉里程计用连续的视差图和相机位姿结合光流信息做双目SLAM这是自动驾驶和无人机领域的重要方向。深度图优化用深度学习的方法对视差图做后处理比如用置信度引导的滤波器或者用Margin-aware的深度补全网络。多基线双目三个或更多相机组合融合多基线信息可以得到更广的范围和更高的精度。对于这些扩展最重要的一步是先把当前系统的精度和稳定性吃透把误差来源摸清楚。比如测试不同光照条件下误差的变化不同目标纹理条件下的成功率这样后续接任何应用层算法都有底气。我个人在实际操作中最深的体会是机械结构对双目测距的稳定性影响被大多数人低估了。相机固定板只要有一点点微小的热胀冷缩或震动都会反映到外参上导致精度下降。所以如果你做的是长期部署的方案建议用铝合金或者碳纤维的固定结构标定好之后用螺丝锁死、上胶固定尽量减少机械形变。还有如果你要长时间运行记得观察相机的发热情况过热会导致图像噪声变大和参数漂移。最后再分享一个小技巧每次上电后先拍一张白纸或均匀光照下的画面观察左右图像亮度是否一致。左右图像亮度相差大说明两个相机传感器状态不同这会对SGBM的匹配造成额外干扰。做一次简单的直方图匹配能明显提升视差图的完整性。本文还有配套的精品资源点击获取