简介:计算机视觉中的立体视觉技术,其核心原理源于三角测量法,通过模拟人眼视差来感知三维空间信息。该技术的关键在于利用两个相机从不同视角捕获图像,通过计算对应像素点的位置差异(即视差),并结合相机标定获得的焦距与基线距离,最终解算出物体的深度。这项技术的工程价值在于,它提供了一种低成本、非接触式的三维感知方案,广泛应用于机器人导航、自动驾驶、三维重建、体积测量及增强现实等领域。本文以双目视觉测距为主题,详细拆解了基于Python和OpenCV的完整实现流程,涵盖了相机标定、立体校正、立体匹配(如SGBM算法)等核心步骤,并深入探讨了参数调优与常见问题排查,为开发者提供了一套可直接复用的工程实践方案。
1. 项目概述:从“看见”到“测量”的跨越
最近在整理硬盘,翻出来一个几年前做的双目视觉测距项目,源码和说明文档都还在。当时做这个的初衷很简单,就是想用两个普通的USB摄像头,像人眼一样,不仅能“看见”物体,还能精确地“知道”它离我有多远。这听起来像是机器人或者自动驾驶的活儿,但其实它的应用场景远不止于此。比如,你想做个自动避障的小车,或者一个能估算包裹体积的智能分拣系统,甚至是一个体感交互的游戏外设,双目视觉测距都是核心的“眼睛”和“尺子”。
这个项目就是基于Python和OpenCV搭建的一套完整的双目测距系统。它不依赖昂贵的专用深度相机(比如Kinect或RealSense),而是利用两个廉价的网络摄像头,通过软件算法计算出深度信息。核心文件“项目说明.zip”里包含了完整的源代码、标定用的棋盘格图片、以及详细的步骤文档。今天,我就把这个项目的里里外外、从原理到代码、从标定到测距的每一个坑和技巧,都拆开了揉碎了讲清楚。无论你是刚接触计算机视觉的学生,还是想在实际项目中应用测距功能的开发者,这篇长文都能给你一套可以直接“抄作业”的完整方案。
2. 双目视觉测距的核心原理:三角测量的数字演绎
在深入代码之前,我们必须先搞懂双目视觉到底是怎么测出距离的。这背后的核心思想,其实和我们人眼判断距离,或者大地测量中的三角测量法,在本质上是相通的。
2.1 视差:距离信息的编码者
想象一下,你闭上左眼只用右眼看,然后再闭上右眼只用左眼看,你会发现近处的物体会在背景上发生明显的左右移动,而远处的物体移动很小。这种因为观察位置(左眼和右眼)不同而产生的物体在成像平面上的位置差异,就叫做视差。
在双目视觉系统中,我们有两个相机,一左一右,它们的光心(可以简单理解为镜头中心)在水平方向上有一定的距离,这个距离称为基线。当一个空间中的点P被两个相机同时拍摄到时,它在左相机图像上的投影点是p_left,在右相机图像上的投影点是p_right。如果我们将两个图像对齐,p_left和p_right的横坐标之差,就是该点的视差。
这里有一个关键公式:深度 Z = (基线 B * 焦距 f) / 视差 d。其中,焦距f和基线B在相机标定后是已知的固定值。视差d是我们通过图像匹配计算出来的。从这个公式可以直观地看出:视差越大,深度越小(物体越近);视差越小,深度越大(物体越远)。当视差为零时(理论上物体在无穷远处),深度为无穷大。这就是双目测距最根本的数学模型。
2.2 极线几何与立体校正:为匹配铺平道路
直接在两幅原始图像上寻找同一个点是非常困难的,因为搜索范围是整个二维图像。极线几何大大简化了这个搜索过程。它告诉我们:对于左图像上的一个点p_left,其在右图像上的对应点p_right,必然位于一条特定的直线上,这条线叫做极线。
但是,在未经处理的原始双目图像中,这些极线可能是倾斜的、弯曲的,搜索起来仍然不方便。立体校正的目的,就是将两个相机的图像平面重投影到同一个平面上,并且让两个相机的光轴平行。经过完美的立体校正后,一个神奇的现象发生了:左图像上的任意一点,其在右图像上的对应点,必定位于同一水平扫描线上。这意味着,我们只需要在右图像的同一行(即同一y坐标)进行水平搜索,就能找到匹配点,将二维搜索降为一维搜索,计算量大大降低,精度和速度都得到提升。
立体校正是整个流程中最关键、也最容易出错的环节之一。它依赖于之前相机标定得到的高精度参数。如果标定不准,校正后的图像就会“扭曲”,导致后续的匹配和测距结果完全错误。
2.3 立体匹配:寻找“孪生”像素点
立体校正后,我们的任务就变成了:对于左图的每一个像素,在右图的同一行上,找到一个最相似的像素。这个过程就是立体匹配。它是双目视觉中最核心、最耗时的算法部分。
匹配的“相似度”如何衡量?通常我们会在目标像素周围取一个小窗口(比如7x7像素),然后计算该窗口与右图候选像素窗口之间的某种距离。常见的计算方法有:
- 绝对误差和:计算两个窗口内所有像素灰度值差的绝对值之和。数值越小越相似。
- 平方误差和:计算灰度值差的平方和。
- 归一化互相关:对光照变化有一定鲁棒性。
OpenCV中提供了多种立体匹配算法,主要分为两类:
- 局部块匹配:例如
StereoBM和StereoSGBM。StereoBM是基本的块匹配算法,速度较快但精度一般,对纹理重复区域敏感。StereoSGBM是半全局块匹配算法,通过在一维路径上动态规划,结合了多个方向上的约束,能得到更平滑、更准确的视差图,是实际项目中的首选。 - 全局匹配:例如
StereoGC,它通过构建全局能量函数并优化来求解视差,精度很高,但计算速度极慢,基本无法用于实时应用。
在我们的项目中,主要使用的是StereoSGBM算法,因为它能在精度和速度之间取得很好的平衡。
3. 项目实战:一步步构建你的双目测距系统
理解了原理,我们来看手把手的实操。整个项目流程可以清晰地分为四个阶段:环境搭建、相机标定、立体校正与匹配、深度计算与后处理。
3.1 环境准备与依赖安装
工欲善其事,必先利其器。一个干净、版本匹配的Python环境是成功的第一步。
Python与OpenCV版本选择:我强烈建议使用Python 3.8或3.9,这两个版本与各类库的兼容性最好。OpenCV方面,选择OpenCV 4.5+的版本。OpenCV 4.x在立体视觉模块上比3.x有更多优化和更好的API。避免使用太新的Python 3.11+,有时会遇到预编译库不兼容的问题。
创建虚拟环境与安装:永远不要在系统Python里直接装包。使用conda或venv创建独立环境。
# 使用conda(推荐) conda create -n stereo_vision python=3.9 conda activate stereo_vision # 使用venv python -m venv stereo_venv # Windows: stereo_venv\Scripts\activate # Linux/Mac: source stereo_venv/bin/activate安装核心库:
pip install opencv-contrib-python==4.5.5.64 pip install numpy pip install matplotlib # 用于可视化标定结果和视差图注意:一定要安装
opencv-contrib-python,它包含了主模块opencv-python以及额外的contrib模块,其中包含了一些立体匹配相关的额外功能。安装时指定版本可以避免后续因版本差异导致的API变化问题。
硬件准备:你需要两个USB摄像头。为了获得好的效果,尽量选择:
- 同型号摄像头:确保两个摄像头的焦距、传感器特性一致,减少标定和校正的难度。
- 固定基线:将两个摄像头牢固地固定在一个支架上,保持光轴大致平行,基线距离(两个摄像头中心的距离)在5cm到20cm之间为宜。基线越长,对远处物体的测距精度越高,但近处物体的盲区也会变大(两个相机都看不到的区域)。
- 手动对焦镜头:如果是可调焦的,将其固定到无穷远,或者固定到一个常用的景深范围。
3.2 双目相机标定:给相机做“体检”
标定的目的是确定每个相机的“内参”和两个相机之间的“外参”。你可以理解为给相机做一次全面的“体检”,得到它的“身份证信息”。
内参描述了相机自身的属性,包括:
- 焦距:成像的缩放比例。
- 主点:图像的中心点(通常接近图像中心,但并非绝对)。
- 畸变系数:由于镜头工艺导致的图像扭曲(径向畸变和切向畸变)。
外参描述了两个相机之间的位置关系,包括:
- 旋转矩阵:右相机坐标系相对于左相机坐标系的旋转。
- 平移向量:右相机原点相对于左相机原点的平移,其x分量就是基线距离B。
标定步骤实操:
- 制作标定板:项目里通常提供了棋盘格图片。你需要将它打印出来,贴在一个非常平整的硬板(如亚克力板)上。棋盘格方格的大小必须精确测量(例如,每个方格25.0毫米),这个值将作为世界坐标的尺度。
- 采集标定图像:用你的双目相机同时拍摄这个标定板。需要拍摄15-25组图像。每组图像中,标定板应出现在两个相机的共同视野内,并且要以不同的角度、距离、位置进行摆放(倾斜、旋转、远近)。确保棋盘格充满图像的大部分区域。将左右相机同步拍摄的图像分别保存在
left/和right/文件夹,并确保文件名对应(如left01.jpg,right01.jpg)。 - 执行标定代码:项目源码中会有一个
calibrate.py或类似的脚本。它的核心是调用cv2.findChessboardCorners来检测棋盘格角点,然后用cv2.stereoCalibrate函数进行双目标定。# 核心代码片段示意 ret, K1, D1, K2, D2, R, T, E, F = cv2.stereoCalibrate( object_points, # 三维世界坐标点 image_points1, # 左图像点 image_points2, # 右图像点 K1, D1, K2, D2, # 初始内参和畸变(可先单目标定获得) image_size, # 图像尺寸 criteria=criteria, flags=cv2.CALIB_FIX_INTRINSIC # 如果已单目标定,则固定内参 )stereoCalibrate会返回我们需要的所有参数:左右相机的内参矩阵K1, K2、畸变系数D1, D2、旋转矩阵R、平移向量T。平移向量T的第一个值T[0]的绝对值,就是基线距离B,单位是标定板方格的单位(如毫米),这是后续深度计算的关键。
标定注意事项与心得:
- 平整性是关键:标定板必须绝对平整,任何弯曲都会引入误差。
- 覆盖整个视野:采集图像时,要让标定板出现在图像的四角和中心,以充分矫正镜头边缘的畸变。
- 检查角点检测:运行标定脚本时,OpenCV会显示每一张图片检测到的角点。你必须肉眼逐一检查,确保所有角点都被正确、精确地检测到。任何一张图的角点检测有误,都会污染整个标定结果。对于检测失败的图片,果断删除。
- 评估重投影误差:
stereoCalibrate的返回值ret就是平均重投影误差,单位是像素。一般来说,这个误差小于0.5像素算是优秀,小于1像素可以接受。如果误差大于2像素,说明标定质量很差,需要重新采集图像。 - 保存标定结果:将标定得到的参数(
K1, D1, K2, D2, R, T)用np.savez保存为.npz文件,后续所有步骤都会加载这个文件。
3.3 立体校正与视差图计算:让图像“对齐”并寻找差异
拿到高精度的标定参数后,我们就可以进行立体校正了。
计算校正映射表:
# 加载标定参数 data = np.load('calibration_params.npz') K1, D1, K2, D2, R, T = data['K1'], data['D1'], data['K2'], data['D2'], data['R'], data['T'] # 计算立体校正参数 R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify( K1, D1, K2, D2, image_size, # 图像尺寸,必须与标定时一致 R, T, alpha=0 # 控制校正后图像的有效区域,0表示裁剪掉黑边,-1表示保留所有像素(有黑边) )cv2.stereoRectify计算出了左右相机分别需要的旋转矩阵R1, R2和新的投影矩阵P1, P2,以及一个重要的重投影矩阵Q。这个Q矩阵包含了从二维图像坐标+视差到三维世界坐标转换的所有信息。生成校正映射表并校正图像:
# 为左图和右图分别计算校正映射表(从原始图像坐标到校正后图像坐标的映射) map1_left, map2_left = cv2.initUndistortRectifyMap(K1, D1, R1, P1, image_size, cv2.CV_16SC2) map1_right, map2_right = cv2.initUndistortRectifyMap(K2, D2, R2, P2, image_size, cv2.CV_16SC2) # 读取左右原始图像 img_left = cv2.imread('left.jpg') img_right = cv2.imread('right.jpg') # 应用映射表,进行校正 img_left_rectified = cv2.remap(img_left, map1_left, map2_left, cv2.INTER_LINEAR) img_right_rectified = cv2.remap(img_right, map1_right, map2_right, cv2.INTER_LINEAR)校正后,你可以将左右图像上下拼接显示,并用
cv2.line在固定行上画水平线。如果校正准确,你会发现左右图中同一个物体的特征点基本位于同一水平线上。配置与运行SGBM匹配器:
# 创建SGBM匹配器对象 window_size = 5 # 匹配窗口大小,奇数,通常3-11 min_disp = 0 # 最小视差 num_disp = 16 * 5 # 视差搜索范围,必须是16的整数倍。值越大,能探测的最近距离越近。 stereo = cv2.StereoSGBM_create( minDisparity=min_disp, numDisparities=num_disp, blockSize=window_size, P1=8 * 3 * window_size ** 2, # 控制视差平滑度的参数,通常按此公式设置 P2=32 * 3 * window_size ** 2, disp12MaxDiff=1, uniquenessRatio=15, # 唯一性比率,值越大匹配越严格 speckleWindowSize=100, # 过滤小连通区域 speckleRange=32, mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY ) # 计算视差图(输入必须是灰度图) gray_left = cv2.cvtColor(img_left_rectified, cv2.COLOR_BGR2GRAY) gray_right = cv2.cvtColor(img_right_rectified, cv2.COLOR_BGR2GRAY) disparity = stereo.compute(gray_left, gray_right).astype(np.float32) / 16.0 # SGBM返回的视差值是16倍整数numDisparities是最重要的参数之一。它定义了搜索范围:从minDisparity到minDisparity + numDisparities。视差图的计算单位是像素。例如,某个点的视差值为d像素。
3.4 从视差到深度:生成你的3D点云
得到视差图后,距离我们就只有一步之遥了。
深度计算: 利用之前立体校正得到的重投影矩阵
Q,我们可以将视差图直接转换为深度图。# 使用reprojectImageTo3D将视差图转换为三维点云 points_3d = cv2.reprojectImageTo3D(disparity, Q) # points_3d是一个与图像同尺寸的三通道矩阵,每个像素位置是一个(X, Y, Z)坐标 # 其中Z就是深度值(通常与世界坐标单位一致,如毫米) depth_map = points_3d[:, :, 2] # 提取Z通道,即深度图也可以手动根据公式计算某个点的深度:
Z = (f * B) / d。但需要注意单位统一:焦距f的单位是像素,基线B的单位是毫米,计算出的Z单位也是毫米。cv2.reprojectImageTo3D帮我们处理了所有这些换算。可视化与测量:
- 视差图可视化:通常视差值较小,直接显示是黑的。需要做归一化处理。
disp_vis = cv2.normalize(disparity, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) disp_vis = cv2.applyColorMap(disp_vis, cv2.COLORMAP_JET) # 用颜色表示视差大小 - 深度图可视化:同样需要归一化,并可以设置一个最大深度阈值,超出部分置为0或特定颜色。
- 鼠标点击测距:在图像窗口上设置鼠标回调函数,点击图像某点,根据该点的
(x, y)坐标,从depth_map或points_3d中读取对应的Z值,即为该点到相机的距离。
- 视差图可视化:通常视差值较小,直接显示是黑的。需要做归一化处理。
4. 性能优化、问题排查与精度提升实战
一套能跑通的代码只是开始,要让它在实际场景中稳定、精确地工作,还需要大量的调优和问题处理。
4.1 立体匹配参数调优指南
StereoSGBM的参数直接影响视差图的质量。下面是一个详细的调参表:
| 参数 | 含义与影响 | 调优建议与常见范围 |
|---|---|---|
minDisparity | 最小视差值。通常设为0。如果相机对得很正,近处物体视差大,可尝试负数。 | 默认0。如果校正后图像中心区域视差普遍较大(>30),可设为负值(如-32)以扩大近处搜索范围。 |
numDisparities | 视差搜索范围。必须是16的整数倍。值越大,能检测的最近距离越近,但计算量也越大。 | 最关键参数。根据基线B和焦距f估算:numDisparities ≈ (f * B) / 最近测距距离。通常从64或128开始尝试。 |
blockSize | 匹配窗口的边长(奇数)。窗口越大,对纹理稀疏区域越鲁棒,但边缘会越模糊。 | 纹理丰富的场景用较小值(3,5);纹理稀疏(如白墙)用较大值(7,11,15)。通常5或7是好的起点。 |
P1, P2 | 控制视差平滑度的惩罚项。P2 > P1。它们鼓励相邻像素视差连续。 | 按经验公式设置通常效果不错:P1 = 8*通道数*blockSize^2,P2 = 32*通道数*blockSize^2。对于灰度图,通道数为1。 |
uniquenessRatio | 唯一性检测比率。值越大,匹配要求越严格,能过滤错误匹配,但也可能增加无效点。 | 常用范围5-15。如果视差图噪声多、误匹配点多,可以适当调高(如15-20)。 |
speckleWindowSize | 视差斑点滤波器窗口大小。用于过滤小的孤立噪声区域。 | 通常设为50-200。设为0禁用滤波。 |
speckleRange | 视差斑点滤波器判断为同一连通分量的最大视差变化值。 | 通常设为1或2。在speckleWindowSize内,视差变化超过此值的区域会被过滤。 |
disp12MaxDiff | 左右一致性检查中允许的最大差异。开启左右检查能大幅提升精度。 | 通常设为1或2。值越小越严格。 |
实操心得:调参时,务必用真实的场景图像进行。准备一个包含不同距离、不同纹理的固定场景。调整一个参数时,固定其他参数,观察视差图的变化。优先调整
numDisparities和blockSize,它们对结果影响最大。目标不是消除所有噪声,而是在保留有效细节和抑制噪声之间找到最佳平衡。
4.2 常见问题、现象与解决方案
在实际运行中,你会遇到各种各样的问题。下面是一个快速排查表:
| 问题现象 | 可能原因 | 排查与解决方案 |
|---|---|---|
| 视差图全黑或全灰 | 1.numDisparities设置太小,实际视差超出范围。2. 图像校正失败,左右图对应点不在同一行。 3. 图像纹理过于单一(如白墙)。 | 1. 增大numDisparities值。2. 检查校正后的图像,画水平线看是否对齐。 3. 增加 blockSize,或考虑在场景中增加纹理(如贴棋盘格纸)。 |
| 视差图噪声极大(雪花点) | 1.blockSize太小,对噪声敏感。2. uniquenessRatio太低,错误匹配多。3. 相机图像有噪点(光照不足)。 | 1. 适当增大blockSize。2. 提高 uniquenessRatio。3. 改善光照,或对输入图像进行高斯滤波预处理(轻微)。 |
| 物体边缘出现“拖尾”或“膨胀” | blockSize太大,导致边缘区域的匹配窗口覆盖了背景和前景,产生平均效应。 | 减小blockSize。这是局部匹配算法的固有缺陷,可考虑后续用WLS滤波器进行视差图后处理。 |
| 深度值跳变或不连续 | 1. 标定误差大,特别是基线B测量不准。 2. 立体校正不理想,存在垂直视差。 3. 相机在拍摄标定板和实际场景间发生了物理位移。 | 1. 重新进行高精度标定,确保标定板平整、角点检测准确。 2. 检查 stereoRectify的alpha参数,尝试不同的值(-1, 0, 0.5)。3.固定好你的双目相机!标定后绝不能移动或碰撞。 |
| 远处物体测距不准或无效 | 1. 基线B太短,远处物体视差小于1像素,超出算法分辨能力。 2. 相机分辨率太低。 | 1. 这是物理限制。增加基线距离可以提升远距离精度,但会牺牲近距离视野。 2. 使用更高分辨率的相机。 |
| 运行速度很慢 | 1. 图像分辨率太高。 2. numDisparities设置过大。3. blockSize设置过大。 | 1. 先对图像进行下采样(如缩放到640x480)进行匹配,得到视差图后再上采样回原尺寸(精度有损失)。 2. 根据实际测距范围,合理减小 numDisparities。3. 在满足需求的前提下使用较小的 blockSize。 |
4.3 高级技巧与精度提升策略
当基础功能实现后,这些技巧能让你的系统更上一层楼。
图像预处理:
- 直方图均衡化:对于光照不均的场景,分别对左右图进行直方图均衡化(
cv2.equalizeHist),可以增强对比度,改善匹配效果。 - 高斯滤波:轻微的滤波(如3x3高斯核)可以平滑图像噪声,但切记不要过度,否则会模糊纹理,反而影响匹配。
- 直方图均衡化:对于光照不均的场景,分别对左右图进行直方图均衡化(
视差图后处理:
- 空洞填充:视差图中无效点(匹配失败的点)会形成空洞。可以用周围有效点的中值或均值进行填充(
cv2.inpaint)。 - WLS滤波:OpenCV的
ximgproc模块提供了加权最小二乘滤波器,能在平滑视差图的同时很好地保留边缘,显著提升视觉质量。这需要额外安装opencv-contrib-python并编译ximgproc模块支持。
# 使用WLS滤波器示例(需安装完整OpenCV contrib) wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=stereo) disparity_filtered = wls_filter.filter(disparity, img_left_rectified, None, img_right_rectified)- 空洞填充:视差图中无效点(匹配失败的点)会形成空洞。可以用周围有效点的中值或均值进行填充(
相机同步与曝光:
- 硬件同步:如果两个相机独立曝光,在拍摄运动物体时会产生“时间差”,导致匹配错误。最好使用支持硬件触发同步的相机。
- 软件同步:对于USB摄像头,可以尝试同时调用
grab()再同时retrieve(),以减少采集时间差。 - 固定曝光与白平衡:在代码中锁定相机的曝光、增益和白平衡参数,避免自动调整导致左右图亮度、颜色不一致。
基线距离的权衡:
- 长基线:提高深度测量精度和远距离测量能力,但会增大盲区(两个相机视野不重叠的区域),且近处物体可能因为视差过大而无法匹配(超出
numDisparities范围)。 - 短基线:盲区小,近处物体匹配成功率高,但深度精度低,尤其是远处。
- 选择:根据你的主要测距范围来选择。如果是室内机器人避障(测距范围0.3m-3m),基线5-10cm即可。如果是室外无人机测距(5m-50m),基线可能需要20cm以上。
- 长基线:提高深度测量精度和远距离测量能力,但会增大盲区(两个相机视野不重叠的区域),且近处物体可能因为视差过大而无法匹配(超出
5. 项目源码结构解析与扩展应用
最后,我们打开“项目说明.zip”,看看一个完整的工程应该如何组织,以及这个双目系统还能玩出什么花样。
一个典型的项目结构如下:
stereo_vision_project/ ├── calibrate/ │ ├── left/ # 存放左相机标定图像 │ ├── right/ # 存放右相机标定图像 │ └── calibration.py # 双目标定脚本 ├── params/ │ └── calibration_params.npz # 保存的标定参数文件 ├── scripts/ │ ├── rectify.py # 立体校正与测试脚本 │ ├── sgbm_match.py # SGBM匹配与视差计算脚本 │ └── measure.py # 实时测距演示脚本(打开摄像头,点击测距) ├── utils/ │ └── visualization.py # 可视化工具函数 ├── main.py # 主程序,集成所有功能 └── requirements.txt # 项目依赖main.py通常会串联整个流程:加载参数 -> 初始化相机 -> 实时获取图像 -> 校正 -> 计算视差 -> 计算深度 -> 显示结果。在实时流中,计算校正映射表initUndistortRectifyMap只需要做一次,后续每一帧都使用remap进行快速校正,这是保证实时性的关键。
扩展应用思路:
- 三维重建:将
reprojectImageTo3D得到的所有点云保存下来(如PLY格式),就可以用MeshLab等软件查看三维模型。 - 障碍物检测:对深度图进行阈值分割,将一定距离内的点聚类,可以识别出前方的障碍物及其位置。
- 体积测量:固定相机拍摄一个物体(如快递盒),通过深度图分割出物体区域,利用点云数据可以估算其长宽高和体积。
- 与SLAM结合:将双目相机作为视觉里程计,通过连续帧间的特征匹配和深度信息,估计相机自身的运动轨迹,构建环境地图。
这个项目最让我有成就感的地方,不是调通了某个参数,而是真正理解了从两个二维图像中恢复出三维信息这一完整链条。每一个环节的误差都会传递和放大,所以耐心做好标定、理解每个参数的意义、仔细处理每一个异常情况,比盲目修改代码更重要。双目视觉是一门实践性极强的技术,最好的学习方式就是像这样,亲手搭建一套系统,然后不断地用它去看不同的场景,解决冒出来的各种问题。希望这份超详细的拆解,能帮你少走些弯路,更快地享受到用代码“看见”三维世界的乐趣。
本文还有配套的精品资源,点击获取