本系列文章旨在系统性地阐述如何利用 Python 与 OpenCV 库,从零开始构建一个完整的双目立体视觉系统。
本项目github地址:https://github.com/present-cjn/stereo-vision-python.git
1. 概述
欢迎来到本系列文章的最后一篇。在过去的几篇文章中,我们已经逐一攻克了相机标定、立体匹配和三维重建这三大核心技术模块。我们拥有了独立的零件,现在可以将它们组装成一台功能完备、性能可靠的机器了。
本文将作为我们项目的最终"用户手册"和"设计复盘"。我们将详细剖析 main.py
是如何作为程序的"大脑",通过命令行界面(CLI)来调度和编排所有模块的。同时,本文也将提供一份比 README.md
更详尽的、包含所有使用场景的完整操作指南。
✨ 主要功能
-
相机标定 :
- 采用高鲁棒性的两步标定法,先进行单目标定,再求解双目相对位姿。
- 自动检测棋盘格角点,并进行亚像素级优化。
- 生成并保存包含内外参、旋转/平移矩阵和畸变系数的 stereo_params.yml 文件。
-
立体匹配 :
- 使用经典的 SGBM (Semi-Global Block Matching) 算法计算视差图。
- 所有SGBM算法的超参数均在 config.py 中可配置。
-
三维重建 :
- 利用视差图和重投影矩阵 Q 将二维图像信息重建为三维点云。
- 对生成的点云进行过滤和降采样以获得更干净的结果。
- 支持将点云数据保存为 .ply 文件,可在其他3D软件(如 MeshLab)中使用。
-
交互式可视化 :
- 提供了两种最终成果的可视化方式:
- 3D点云显示:使用 Open3D 库进行交互式三维点云可视化(可选安装)。
- 交互式深度图:实时显示伪彩色的深度图,当鼠标悬停在图像上时,可以显示该像素点的真实世界距离(毫米)。
- 提供"详细模式" (--verbose),可以显示校正图像对、原始视差图等所有中间调试步骤。
-
专业的工程实践 :
- 模块化设计: 将不同功能(标定、处理、工具、可视化)解耦到独立的模块中。
- 命令行界面: 基于 argparse 构建,支持 calibrate 和 run 等不同子命令,并提供详细的帮助信息。
- 自动化测试: 包含 pytest 单元测试和稳定性测试,确保代码质量和算法的健壮性。
- 依赖管理: 使用 requirements.txt 文件管理核心依赖,并支持可选依赖(open3d)。
📂 项目结构
stereo-vision-project/
├── 📄 main.py # 主程序入口,命令行界面
├── 📄 config.py # 所有配置参数
├── 📄 requirements.txt # 项目核心依赖
|
├── 📁 calibration/ # 📷 相机标定模块
│ └── calibrator.py
│
├── 📁 processing/ # 核心处理模块
│ ├── stereo_matcher.py # 立体匹配
│ └── reconstructor.py # 三维重建
│
├── 📁 utils/ # 🛠️ 通用工具函数
│ ├── file_utils.py # 文件读写
│ ├── image_utils.py # 图像处理
│ └── sorting_utils.py # 自然排序
│
├── 📁 visualization/ # 📊 可视化模块
│ └── visualizer.py
│
├── 📁 tests/ # 测试代码
│ ├── test_calibration.py
│ └── test_calibration_stability.py
│
└── 📁 data/ # 🗃️ 数据
├── calibration_images/ # 用于标定的棋盘格图片
└── test_images/ # 用于立体匹配的测试图片
2. 设计回顾
在我们开始深入 main.py
之前,有必要再次回顾我们的项目架构。我们没有将所有代码都写在一个文件里,而是设计了 calibration
, processing
, utils
, visualization
等多个模块。
这种模块化设计的核心优势在于解耦------每个模块都像一个独立的专家,只负责自己的工作。
而main.py
它不执行任何具体的算法,它的唯一职责就是任务调度 和用户交互。它通过解析用户的命令行指令,来决定应该"聘请"哪位专家(调用哪个类),并为它们提供必要的"工具"和"原材料"(传递配置和数据)。
main.py
命令行接口详解
我们使用 Python 内置的 argparse
库来构建一个专业、灵活的命令行界面。这使得我们的程序不再是一个简单的脚本,而是一个真正的工具。
全局选项:--verbose
/ -v
我们设计了一个对所有子命令都有效的全局选项 --verbose
。这在命令行工具设计中是一个非常标准的实践。
- 作用: 控制程序的"详细程度"。当启用此标志时,程序会显示所有中间过程的可视化结果(如角点检测图、校正图、原始视差图),并可能打印更详细的日志。
- 实现 : 我们在主解析器
parser
上定义这个参数,并在程序启动时,用它的值去设置一个全局的配置状态config.VERBOSE_MODE
。这样,任何模块都可以通过查询config.VERBOSE_MODE
来决定自己的行为,而无需与argparse
直接耦合。
子命令一:calibrate
此命令负责执行完整的相机标定流程。我们为它设计了极其灵活的参数处理方式,兼顾了开发者的便利性和最终用户的灵活性。
- 核心参数 :
--corners <宽>,<高>
: 用于指定标定板的内角点数量。--size <边长mm>
: 用于指定标定板方格的物理尺寸。
- "配置作为默认,参数作为覆盖"模式 :
- 对于开发者 : 在 IDE 中直接运行
python main.py calibrate
时,程序会自动从config.py
中读取DEFAULT_CHESSBOARD_SIZE
和DEFAULT_SQUARE_SIZE_MM
作为参数。这使得调试过程无需任何额外配置。 - 对于用户 : 用户可以通过命令行提供
--corners
和--size
参数,这些参数会覆盖掉config.py
中的默认值,使其可以使用任何规格的标定板。
- 对于开发者 : 在 IDE 中直接运行
子命令二:run
此命令负责执行从图像加载到最终结果可视化的完整流水线。
- 核心参数 :
--view-3d
: 这是一个可选的布尔标志。
- 默认行为 :
python main.py run
会执行所有计算,保存点云文件,并默认显示交互式2D深度图。这是核心的、最轻量的可视化功能。 - 可选功能 : 如果用户安装了
open3d
库并希望查看三维结果,可以添加--view-3d
标志。程序会在显示2D深度图的同时,额外弹出一个可交互的3D点云窗口。 - "渐进式增强"设计 : 我们将
open3d
设计为一个可选依赖 。表示即使用户没有安装这个大型库,项目的核心功能(包括2D深度图显示)也完全可以正常运行。只有在用户尝试使用--view-3d
时,程序才会检查open3d
是否存在,如果不存在,则会给出安装提示。
3. 完整使用手册
现在我们从克隆这个项目开始进行一次完整的演示。
3.1. 准备工作
-
克隆项目并进入目录:
git clone https://github.com/present-cjn/stereo-vision-python.git
cd stereo-vision-project -
创建并激活虚拟环境:
python -m venv venv
source venv/bin/activate -
安装依赖:
安装核心依赖
pip install -r requirements.txt
(可选) 安装3D可视化依赖
pip install open3d
3.2. 执行相机标定
-
目标 : 生成
output/stereo_params.yml
文件。 -
准备 : 你需要准备好一组双目相机拍摄的棋盘格图片,并将你的标定图片已放入
data/calibration_images/
,左右图像分别以 leftPic\*.jpg 和 rightPic\*.jpg 命名。如果想要使用其他自定义路径,可以修改config.py
中的CALIBRATION_IMAGE_DIR
-
命令:
使用项目自带的标定图片,可以直接运行(使用config.py中的默认值)
python main.py calibrate
使用你自己的标定板参数运行
python main.py calibrate --corners 11,8 --size 12
如果想观察每一步的角点检测效果
python main.py -v calibrate --corners 11,8 --size 12
用--verbose
/ -v
参数时可以看到如下过程图,表示找到了对应的棋盘角点

3.3. 运行主程序并查看结果
-
目标: 计算视差图、重建三维点云,并进行可视化。
-
准备 : 确保
output/stereo_params.yml
已存在,并在config.py
中配置好测试图片的路径。 -
命令:
默认行为:显示交互式2D深度图
python main.py run
额外显示3D点云(需要已安装open3d)
python main.py run --view-3d
如果想显示所有中间过程,并最终显示点云,则用下述命令
python main.py -v run --view-3d
用--verbose
/ -v
参数时可以看到如下过程图
完成极线校正

完成视差图计算

完成深度图显示(鼠标放置右边的某个点即可显示当前点的深度信息)

完成点云图

3.4. 获取帮助
-
目标: 查看所有可用的命令和参数。
-
命令:
python main.py --help
python main.py calibrate --help
python main.py run --help
3.5. 参数配置
项目中的所有可调参数都集中在 config.py 文件中,包括:
- 文件和目录路径。
- 用于快速调试的默认棋盘格参数,可在运行时被命令行覆盖。
- SGBM 算法的所有超参数。
- 算法的终止条件 criteria。
4. 总结与展望
通过这个系列,我们不仅实现了一个功能完备的双目视觉系统,还遵循专业的软件工程实践,构建了一个模块化、可测试、易于维护和扩展的项目。
这只是一个起点。基于这个框架,你可以继续探索更多有趣的方向:
- 实时处理 : 修改
main.py
以从摄像头实时读取视频流,并进行实时深度估计。 - 目标检测与测距: 结合一个目标检测模型(如 YOLO),在检测到物体的同时,利用我们的深度信息来测量它与相机之间的距离。
- 算法替换 : 尝试用
StereoBM
替换StereoSGBM
,或者探索更先进的基于深度学习的匹配算法,并对比它们的效果。
本系列文章的使命是为探索计算机视觉领域的开发者,提供一份详尽的实践指南。如果本项目对您有所帮助,希望在 GitHub 上为其点亮星标 (Star) 以示支持。此外,任何技术问题或功能建议,均可通过提交 Issue 或评论提问的方式进行探讨。感谢您的阅读与支持!