用Python和OpenCV从零搭建一个完整的双目视觉系统(六 最终篇)

本系列文章旨在系统性地阐述如何利用 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)中使用。
  • 交互式可视化 :

    • 提供了两种最终成果的可视化方式:
    1. 3D点云显示:使用 Open3D 库进行交互式三维点云可视化(可选安装)。
    2. 交互式深度图:实时显示伪彩色的深度图,当鼠标悬停在图像上时,可以显示该像素点的真实世界距离(毫米)。
    • 提供"详细模式" (--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_SIZEDEFAULT_SQUARE_SIZE_MM 作为参数。这使得调试过程无需任何额外配置。
    • 对于用户 : 用户可以通过命令行提供 --corners--size 参数,这些参数会覆盖掉 config.py 中的默认值,使其可以使用任何规格的标定板。
子命令二:run

此命令负责执行从图像加载到最终结果可视化的完整流水线。

  • 核心参数 :
    • --view-3d: 这是一个可选的布尔标志。
  • 默认行为 : python main.py run 会执行所有计算,保存点云文件,并默认显示交互式2D深度图。这是核心的、最轻量的可视化功能。
  • 可选功能 : 如果用户安装了 open3d 库并希望查看三维结果,可以添加 --view-3d 标志。程序会在显示2D深度图的同时,额外弹出一个可交互的3D点云窗口。
  • "渐进式增强"设计 : 我们将 open3d 设计为一个可选依赖 。表示即使用户没有安装这个大型库,项目的核心功能(包括2D深度图显示)也完全可以正常运行。只有在用户尝试使用 --view-3d 时,程序才会检查 open3d 是否存在,如果不存在,则会给出安装提示。

3. 完整使用手册

现在我们从克隆这个项目开始进行一次完整的演示。

3.1. 准备工作
  1. 克隆项目并进入目录:

    git clone https://github.com/present-cjn/stereo-vision-python.git
    cd stereo-vision-project

  2. 创建并激活虚拟环境:

    python -m venv venv
    source venv/bin/activate

  3. 安装依赖:

    安装核心依赖

    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 或评论提问的方式进行探讨。感谢您的阅读与支持!

相关推荐
EutoCool44 分钟前
Qt:布局管理器Layout
开发语言·c++·windows·嵌入式硬件·qt·前端框架
Cyanto1 小时前
Spring注解IoC与JUnit整合实战
java·开发语言·spring·mybatis
在努力的韩小豪1 小时前
如何从0开始构建自己的第一个AI应用?(Prompt工程、Agent自定义、Tuning)
人工智能·python·llm·prompt·agent·ai应用·mcp
云卓SKYDROID1 小时前
无人机环境感知系统运行与技术难点!
人工智能·计算机视觉·目标跟踪·无人机·科普·高科技·云卓科技
写不出来就跑路1 小时前
WebClient与HTTPInterface远程调用对比
java·开发语言·后端·spring·springboot
悠哉清闲2 小时前
C++ MediaCodec H264解码
开发语言·c++
张人玉2 小时前
c#中Random类、DateTime类、String类
开发语言·c#
Jinkxs2 小时前
JavaScript性能优化实战技术
开发语言·javascript·性能优化
Otaku love travel3 小时前
实施运维文档
运维·windows·python
测试老哥3 小时前
软件测试之单元测试
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例