本系列文章旨在系统性地阐述如何利用 Python 与 OpenCV 库,从零开始构建一个完整的双目立体视觉系统。
本项目github地址:https://github.com/present-cjn/stereo-vision-python.git
项目架构设计:蓝图、分工与工作流
在上一篇文章中,我们了解了双目立体视觉的基本原理和核心流程。在正式编写算法之前,我们必须先做好一件事——搭建一个坚实、清晰、可扩展的项目框架。
这就像建造一座大厦,我们不能直接开始砌墙,而是需要先有一份精密的建筑蓝图。一个好的项目架构,能让我们的代码思路清晰、易于维护、便于测试,并且在未来增加新功能时游刃有余。告别将所有代码都堆砌在单个文件里的“面条式代码”,是每一位开发者从入门走向专业的必经之路。
本文将详细剖析我们这个双目视觉项目的“建筑蓝图”,解释每个模块的职责分工和它们之间的协作关系。
📂 项目目录结构一览
下面是项目的整体目录结构,这个结构是我们所有讨论的基础。
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/ # 测试代码
│ └── ...
└── data/ # 数据
├── calibration_images/
└── test_images/
程序入口与任务调度:main.py
main.py
是我们整个项目的唯一入口和总指挥。它的职责不是执行具体的算法,而是扮演一个“应用启动器”和“任务分发器”的角色。
- 命令行界面 (CLI): 我们使用 Python 内置的
argparse
库,将main.py
打造成一个专业的命令行工具。用户可以通过python main.py calibrate
或python main.py run
来执行不同的任务,并通过--verbose
或--view-3d
等参数来控制程序的行为。 - 任务编排:
main.py
负责按照逻辑顺序,调用其他模块中的类和函数,将整个双目视觉的流水线串联起来。它负责加载配置、执行标定或主应用流程,并最终呈现结果。
全局配置与状态管理:config.py
这个文件是我们项目的全局配置中心。它遵循一个重要的设计原则:配置与代码分离。
- 集中管理: 所有可以调整的参数,如文件路径、算法超参数(SGBM的参数)、标定板的默认尺寸等,都集中存放在这里。
- 便于调试与维护: 当我们需要调整算法效果时,只需要修改
config.py
中的数值,而无需触及核心的算法逻辑代码。这极大地提高了代码的可维护性。 - 运行时状态: 它也承载了像
VERBOSE_MODE
这样的全局运行时状态,由main.py
在启动时根据命令行参数设置,供所有其他模块查询。
核心算法模块:calibration/
与 processing/
这两个目录存放了项目最核心的算法逻辑,每个模块都负责一个独立的、高度内聚的功能。
calibration/calibrator.py
: 负责相机标定。该模块实现了完整的两步标定法,用于计算相机的内外参及畸变参数,并生成最终的stereo_params.yml
配置文件。processing/stereo_matcher.py
: 负责立体匹配。该模块使用 SGBM (半全局块匹配) 算法,接收校正后的图像对,计算并生成包含深度信息的视差图。processing/reconstructor.py
: 负责三维重建。该模块接收视差图和相机几何参数,通过reprojectImageTo3D
函数将2D视差信息转换为3D空间中的点云。
通用工具函数模块:utils/
utils/
目录存放了各种通用的、可被项目中任何模块复用的辅助函数。
file_utils.py
: 负责所有与文件系统交互的操作,如保存和加载.yml
标定文件、保存.ply
点云文件。image_utils.py
: 负责通用的图像处理任务,最核心的就是rectify_stereo_pair
函数,用于立体校正。sorting_utils.py
: 提供natural_sort_key
函数,解决在加载文件时left_10.jpg
排在left_2.jpg
前面的问题。
将这些工具函数独立出来,能避免在多个地方写重复的代码,并让核心算法模块的逻辑更纯粹。
可视化与用户交互模块:visualization/
这个模块负责所有与用户界面和结果展示相关的工作。它的职责是将程序内部的数据,以一种人类可读的方式呈现出来。
- 它包含了显示各种中间结果(如角点图、校正图、视差图)和最终成果(点云、交互式深度图)的函数。
- 它还负责处理所有的用户界面交互,比如
_wait_for_key_or_window_close
辅助函数,确保程序能正确响应用户的键盘和鼠标操作。
自动化测试模块:tests/
tests/
目录存放了我们所有的自动化测试脚本。
- 单元测试: 验证某个独立的函数或类是否按预期工作。
- 稳定性测试: 验证我们的算法(如两步标定法)是否对输入顺序等无关变量不敏感,保证其健壮性。
- 自动化: 通过
pytest
框架,我们可以一键运行所有测试,确保任何新的代码改动都没有破坏已有的功能。这是保证项目长期健康、可维护的基石。
总结
通过这样一种模块化的架构设计,我们将一个复杂的大问题,分解成了一系列职责单一、易于管理的小问题。每个模块都可以被独立地开发、测试和改进。
在下一篇文章中,我们将正式深入第一个核心算法模块——calibration
,剖析相机标定的每一个技术细节和代码实现。