保姆级教程:在Ubuntu 18.04上用OpenCV C++搞定双目摄像头测距(附完整项目源码)

📅 2026/7/28 3:56:23 👁️ 阅读次数 📝 编程学习
保姆级教程:在Ubuntu 18.04上用OpenCV C++搞定双目摄像头测距(附完整项目源码)

从零构建双目视觉测距系统:Ubuntu 18.04实战指南

双目视觉技术正逐渐成为机器人导航、自动驾驶和工业检测领域的标配方案。不同于单目摄像头依赖先验信息的局限性,双目系统通过模拟人眼视差原理,可直接计算物体深度信息。本文将带您从零搭建一套完整的双目测距系统,涵盖环境配置、标定参数转换、代码调试等全流程实战细节。

1. 开发环境搭建与OpenCV编译

在Ubuntu 18.04上构建双目视觉系统,首要任务是配置支持双目算法的OpenCV环境。官方预编译版本通常不包含contrib模块的关键功能,因此需要从源码编译。

1.1 系统依赖安装

执行以下命令安装基础编译工具和依赖库:

sudo apt-get update sudo apt-get install -y build-essential cmake git libgtk2.0-dev sudo apt-get install -y pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev

特别提醒:Ubuntu 18.04默认的GCC版本为7.5,完全兼容OpenCV 4.3.0。若使用更高版本系统,需注意GLIBC兼容性问题。

1.2 OpenCV源码编译

建议在用户目录下创建专门的开发空间:

mkdir ~/vision_ws && cd ~/vision_ws git clone --branch 4.3.0 https://github.com/opencv/opencv.git git clone --branch 4.3.0 https://github.com/opencv/opencv_contrib.git

配置编译选项时,务必启用以下关键模块:

cd opencv && mkdir build && cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \ -D WITH_TBB=ON \ -D WITH_OPENMP=ON \ -D OPENCV_ENABLE_NONFREE=ON \ -D BUILD_EXAMPLES=OFF \ -D BUILD_opencv_python3=OFF \ -D BUILD_TESTS=OFF ..

注意:编译过程可能持续30-60分钟,建议使用make -j$(nproc)加速。完成后执行sudo make install安装。

2. 双目摄像头标定实战

精确的相机标定是双目测距的基础。虽然OpenCV提供标准标定工具,但在实际项目中常遇到标定结果转换问题。

2.1 标定数据采集技巧

使用OpenCV的stereo_calib.cpp示例采集图像时,建议:

  • 保持棋盘格平整(可粘贴在硬质平板上)
  • 覆盖相机视野的不同位置和角度
  • 左右摄像头同步采集(硬件触发最佳)
  • 每组采集15-20张有效图像

典型采集命令:

./stereo_calib -w=9 -h=6 -s=0.025 -showrectify -left=/path/to/left_imgs/ -right=/path/to/right_imgs/

2.2 标定参数解析与应用

标定输出的stereo_calibration.yml包含以下关键参数:

参数组关键参数说明
CameraMatrix1fx, fy, cx, cy左相机内参矩阵
DistCoeffs1k1, k2, p1, p2, k3左相机畸变系数
CameraMatrix2fx, fy, cx, cy右相机内参矩阵
DistCoeffs2k1, k2, p1, p2, k3右相机畸变系数
R旋转矩阵右相机相对于左相机的旋转
T平移向量右相机相对于左相机的平移
E本质矩阵立体几何关系
F基础矩阵极线约束关系

在C++代码中加载这些参数时,需特别注意YAML文件的编码格式。遇到乱码时可使用iconv转换:

iconv -f GBK -t UTF-8 stereo_calibration.yml > stereo_calibration_utf8.yml

3. 测距核心代码实现

双目测距的核心流程包括图像校正、视差计算和深度转换三个关键阶段。

3.1 图像校正实现

使用标定参数初始化校正映射:

Mat R1, R2, P1, P2, Q; stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 0, imageSize); initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R1, P1, imageSize, CV_32FC1, map11, map12); initUndistortRectifyMap(cameraMatrix2, distCoeffs2, R2, P2, imageSize, CV_32FC1, map21, map22);

实时校正处理:

remap(leftFrame, leftRectified, map11, map12, INTER_LINEAR); remap(rightFrame, rightRectified, map21, map22, INTER_LINEAR);

3.2 视差计算优化

SGBM(Semi-Global Block Matching)算法在精度和效率间取得较好平衡:

Ptr<StereoSGBM> sgbm = StereoSGBM::create( minDisparity, numDisparities, blockSize, P1=8*channels*blockSize*blockSize, P2=32*channels*blockSize*blockSize, disp12MaxDiff=1, preFilterCap=63, uniquenessRatio=10, speckleWindowSize=100, speckleRange=32, mode=StereoSGBM::MODE_SGBM_3WAY);

提示:实际部署时可调整以下参数提升效果:

  • 减小numDisparities提高速度
  • 增大uniquenessRatio减少误匹配
  • 启用MODE_HH获取更平滑结果

4. 项目工程化与性能优化

将算法集成到实际项目时,需要考虑代码结构、实时性和部署便利性。

4.1 CMake工程配置

完整的CMakeLists.txt应包含以下关键内容:

cmake_minimum_required(VERSION 3.10) project(StereoVision) set(CMAKE_CXX_STANDARD 11) find_package(OpenCV REQUIRED) add_executable(stereo_depth src/main.cpp src/stereo_calib.cpp src/disparity.cpp) target_link_libraries(stereo_depth ${OpenCV_LIBS}) install(TARGETS stereo_depth DESTINATION bin)

4.2 实时性能优化技巧

  • 图像降采样:在保证精度的前提下,将1080p输入降为720p处理
  • ROI处理:只计算感兴趣区域的视差
  • 异步流水线:使用双缓冲机制分离采集与处理线程
  • GPU加速:对校正和视差计算模块启用CUDA:
cuda::GpuMat gpuLeft, gpuRight, gpuDisp; gpuLeft.upload(leftRectified); gpuRight.upload(rightRectified); Ptr<cuda::StereoBM> stereo = cuda::createStereoBM(numDisparities, blockSize); stereo->compute(gpuLeft, gpuRight, gpuDisp); gpuDisp.download(disp);

实际测试表明,在NVIDIA Jetson Xavier上,CUDA加速可使处理速度提升5-8倍。

5. 常见问题排查指南

双目系统实施过程中常遇到以下典型问题:

5.1 标定失败排查

  • 问题现象:重投影误差大于0.5像素
  • 可能原因
    • 棋盘格图像模糊或未完全显示
    • 标定板物理尺寸输入错误
    • 左右图像未严格同步
  • 解决方案
    • 使用更高对比度的标定板
    • 验证-w-h-s参数与实际物理尺寸一致
    • 检查相机时间戳或使用硬件触发

5.2 视差图质量问题

  • 问题现象:视差图出现大面积噪声或条纹
  • 调试步骤
    1. 检查校正后的图像是否行对齐
    2. 逐步调整SGBM参数:
      • 先设置minDisparity=0numDisparities=64
      • 逐步增加blockSize直到获得稳定结果
    3. 添加后处理滤波:
    Mat filteredDisp; cv::ximgproc::weightedMedianFilter( disp, leftRectified, filteredDisp, 15);

5.3 深度测量误差分析

当实测深度值与真实值偏差较大时,建议检查:

  1. 标定时的基线距离(T向量长度)是否准确
  2. 相机安装是否发生物理位移
  3. 目标物体是否具有足够的纹理特征
  4. 视差计算区域是否包含有效像素

一个实用的验证方法是测量已知距离的标定板,建立误差补偿模型。在3米范围内,良好标定的系统误差应小于2%。

6. 进阶扩展方向

完成基础测距功能后,可考虑以下增强方案:

  • 多相机同步系统:通过PTP协议实现多设备纳秒级同步
  • 动态标定:使用AprilTag等标记物实现在线标定更新
  • 深度学习融合:将传统算法与神经网络预测结果融合:
# 示例伪代码:使用ONNX Runtime加载深度学习模型 import onnxruntime as ort sess = ort.InferenceSession("dispnet.onnx") inputs = {"left": left_np, "right": right_np} disp_pred = sess.run(None, inputs)[0]
  • 点云可视化:将深度图转换为3D点云并集成到ROS或Unity环境:
reprojectImageTo3D(disp, pointCloud, Q, true);

在实际机器人项目中,建议将双目系统与IMU数据进行融合,通过卡尔曼滤波提升动态环境下的测距稳定性。