本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:双目视觉立体匹配是一种通过双摄像头图像重建三维场景的技术,核心在于寻找左右图像中像素的对应关系,从而计算深度信息。本项目“litipipei_双目视觉立体匹配_”基于OpenCV库,使用Block Matching(BM)算法,实现了从双目图像输入到深度图输出的完整流程。项目内容涵盖图像预处理、匹配成本矩阵构建、代价聚合、视差计算与后处理等关键步骤。适用于机器人导航、自动驾驶、虚拟现实等场景,是学习计算机视觉和立体匹配算法的理想实践项目。
litipipei_双目视觉立体匹配_

1. 双目视觉立体匹配技术概述

双目视觉作为计算机视觉的关键技术之一,模拟人类双眼的视差感知机制,通过两台摄像机从不同角度拍摄同一场景,进而重建三维空间信息。其核心在于 立体匹配 ,即寻找左右图像中像素点的对应关系,从而生成视差图与深度图。

随着自动驾驶、机器人导航、增强现实等领域的快速发展,立体匹配技术的重要性日益凸显。它不仅要求高精度的像素级匹配,还需兼顾实时性与鲁棒性。早期基于区域的匹配方法如 Block Matching (BM)算法因其结构简单、易于实现,被广泛应用于工程实践中。

本章将系统介绍立体匹配的基本概念、发展历程及其在实际场景中的应用价值,为后续深入探讨其算法实现与优化策略打下坚实基础。

2. Block Matching (BM) 算法原理

Block Matching(BM)算法是立体匹配领域中最基础、最直观的一类局部匹配算法。它通过在左右图像中滑动固定大小的图像窗口,计算窗口之间的匹配代价,从而估计出像素点的视差值。该算法结构简单、易于实现,适合在资源受限的硬件平台或对实时性要求较高的场景中使用。本章将深入剖析BM算法的核心思想、实现流程以及其优缺点,帮助读者建立对立体匹配技术中局部方法的系统理解。

2.1 Block Matching 算法基本思想

Block Matching算法的核心思想是通过比较左右图像中对应窗口的相似性,来寻找最佳的匹配点。该算法假设图像中局部区域的结构在左右图像中保持一致,从而可以基于窗口匹配的方式进行视差估计。其关键在于如何定义窗口、如何度量相似性,以及如何在搜索范围内进行匹配。

2.1.1 基于窗口的匹配机制

在BM算法中,图像被划分为多个固定大小的窗口(如 5×5、7×7 或 9×9),每个窗口以中心像素点为参考点,在左图像中选定一个窗口后,右图像中在一个预设的搜索范围内滑动相同大小的窗口,寻找与左窗口最相似的区域。

窗口匹配流程图如下:

graph TD
    A[左图像窗口中心点] --> B[设定窗口大小]
    B --> C[在右图像中定义搜索范围]
    C --> D[逐个滑动窗口并计算相似度]
    D --> E[选取相似度最高点作为匹配点]
    E --> F[计算该点视差值]

窗口大小的选择直接影响算法的性能:较小的窗口可以提高细节区域的匹配精度,但对噪声敏感;较大的窗口能增强鲁棒性,但可能模糊边缘信息,降低视差分辨率。

2.1.2 相似性度量方法(如SAD、SSD、NCC)

为了衡量两个窗口之间的相似性,BM算法常用以下几种匹配代价函数:

度量方法 公式 特点
SAD(Sum of Absolute Differences) $ \sum_{x,y} I_L(x,y) - I_R(x+d,y)
SSD(Sum of Squared Differences) $ \sum_{x,y} (I_L(x,y) - I_R(x+d,y))^2 $ 对大差异更敏感,计算量略大
NCC(Normalized Cross Correlation) $ \frac{\sum (I_L(x,y) - \bar{I_L})(I_R(x+d,y) - \bar{I_R})}{\sqrt{\sum (I_L(x,y) - \bar{I_L})^2 \sum (I_R(x+d,y) - \bar{I_R})^2}} $ 对光照变化鲁棒性强,但计算复杂

示例代码:SAD匹配代价计算

import numpy as np

def compute_SAD(left_window, right_window):
    return np.sum(np.abs(left_window - right_window))

def block_matching_sad(left_img, right_img, window_size=5, max_disparity=64):
    height, width = left_img.shape
    disparity_map = np.zeros_like(left_img, dtype=np.uint8)

    half_window = window_size // 2

    for y in range(half_window, height - half_window):
        for x in range(half_window, width - half_window):
            best_cost = float('inf')
            best_d = 0
            for d in range(0, max_disparity):
                if x - d - half_window < 0:
                    continue
                left_window = left_img[y-half_window:y+half_window+1, x-half_window:x+half_window+1]
                right_window = right_img[y-half_window:y+half_window+1, x-d-half_window:x-d+half_window+1]
                cost = compute_SAD(left_window, right_window)
                if cost < best_cost:
                    best_cost = cost
                    best_d = d
            disparity_map[y, x] = best_d

    return disparity_map

代码逻辑分析:

  • 函数 compute_SAD :计算两个窗口之间的SAD代价,即对窗口中每个像素点取绝对差值并求和。
  • 函数 block_matching_sad :主函数,对左图像中每个像素点构建窗口,在右图像中搜索匹配点。
  • window_size :窗口大小,默认为5×5。
  • max_disparity :最大视差范围,限制搜索的范围。
  • 双重循环遍历图像 :对图像中每个像素点构建窗口,滑动搜索视差。
  • 选择最佳视差 :记录最小SAD代价对应的视差值作为该点的视差。

2.2 BM算法的实现流程

BM算法的实现主要包括图像窗口滑动、搜索范围设定、成本矩阵计算与最小值选取等步骤。这些步骤构成了完整的匹配流程,直接影响算法的性能和效率。

2.2.1 图像窗口滑动与搜索范围设定

图像窗口的滑动过程是BM算法中最基础的实现步骤。在实际操作中,窗口从左图像的每个像素点出发,在右图像中向左搜索一定范围(即视差范围)内的像素点,比较每个位置的匹配代价。

搜索范围设定影响因素:

  • 视差范围(max_disparity) :决定右图像中搜索窗口的横向移动范围。
  • 图像分辨率 :高分辨率图像需要更大的搜索范围,但会增加计算量。
  • 硬件资源限制 :嵌入式系统或实时系统中需控制搜索范围以满足性能要求。

示意图:

graph LR
    A[左图像] --> B[中心像素点]
    B --> C[构建窗口]
    C --> D[右图像]
    D --> E[设定搜索范围]
    E --> F[滑动窗口进行匹配]

2.2.2 成本矩阵的计算与最小值选取

在BM算法中,成本矩阵记录了每个像素点在不同视差下的匹配代价。最终的视差图是通过对成本矩阵在每个像素点处选取最小代价所对应的视差值得到的。

成本矩阵示例:

视差值 像素点 (x, y) 的 SAD 成本
0 120
1 90
2 60
3 80
4 100

在该示例中,视差值为2时,匹配代价最小,因此该像素点的视差值设为2。

示例代码:构建成本矩阵并选择最小视差值

def build_cost_matrix(left_img, right_img, window_size=5, max_disparity=64):
    height, width = left_img.shape
    cost_matrix = np.zeros((height, width, max_disparity), dtype=np.float32)

    half_window = window_size // 2

    for y in range(half_window, height - half_window):
        for x in range(half_window, width - half_window):
            for d in range(max_disparity):
                if x - d < half_window:
                    cost_matrix[y, x, d] = float('inf')
                    continue
                left_window = left_img[y-half_window:y+half_window+1, x-half_window:x+half_window+1]
                right_window = right_img[y-half_window:y+half_window+1, x-d-half_window:x-d+half_window+1]
                cost = compute_SAD(left_window, right_window)
                cost_matrix[y, x, d] = cost

    # 选择最小代价对应的视差值
    disparity_map = np.argmin(cost_matrix, axis=2)
    return disparity_map

代码逻辑分析:

  • 构建成本矩阵 cost_matrix :三维数组,记录每个像素点在不同视差下的匹配代价。
  • 遍历每个像素点和视差值 :对每个点计算不同视差下的SAD值。
  • 处理边界情况 :当视差值过大导致窗口越界时,设为无穷大,避免误匹配。
  • 使用 np.argmin 获取视差图 :找到每个像素点在所有视差中最小代价所对应的视差值。

2.3 BM算法的优缺点分析

BM算法因其结构简单、易于实现而广泛应用于实时系统中,但其精度受限于局部匹配机制和相似性度量方式,存在一些明显的局限性。

2.3.1 实时性优势与精度限制

实时性优势:

  • 低计算复杂度 :基于局部窗口的匹配策略计算简单,适合硬件加速。
  • 并行性高 :每个像素点的视差计算相互独立,便于并行化处理。
  • 适用于嵌入式系统 :在FPGA、GPU等平台上可实现高效部署。

精度限制:

  • 对边缘和角点匹配效果差 :窗口机制容易导致边缘模糊。
  • 受光照和噪声影响大 :尤其在SAD/SSD等简单度量方法下表现明显。
  • 无法处理大范围遮挡问题 :遮挡区域缺乏对应点,匹配失败概率高。

2.3.2 对重复纹理与遮挡区域的敏感性

重复纹理问题:

当图像中存在大面积重复纹理(如砖墙、草地)时,多个窗口可能具有相似的特征,导致误匹配。NCC等归一化方法可以在一定程度上缓解这一问题,但仍难以完全避免。

遮挡区域问题:

遮挡区域在右图像中没有对应的像素点,导致匹配失败。BM算法缺乏全局优化机制,无法有效识别和处理遮挡区域。

优化思路:

  • 引入代价聚合(Cost Aggregation) :对窗口匹配结果进行平滑处理,提升鲁棒性。
  • 结合左右一致性检测(Left-Right Consistency Check) :通过双向匹配检测遮挡区域。
  • 融合全局优化算法(如SGM) :提高对复杂纹理和遮挡场景的适应能力。

对比表格:

特性 Block Matching (BM) 优化方法(如SGM)
实时性
匹配精度 一般
抗噪声能力
遮挡处理能力
实现复杂度

综上,BM算法在立体匹配中具有良好的实时性与实现简易性,但其在复杂场景下的精度和鲁棒性仍有待提升。在后续章节中,我们将介绍如何通过代价聚合、全局优化等方式进一步提升匹配效果,并结合OpenCV等工具实现完整的立体匹配系统。

3. OpenCV 图像处理基础

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉与机器学习软件库,广泛应用于图像处理、视频分析、特征检测、目标识别等领域。本章将从 OpenCV 的基本使用出发,介绍图像处理的基础操作,包括图像读取与显示、通道处理、图像变换与校正等内容,帮助读者掌握构建双目视觉系统所需的核心图像处理技能。

3.1 OpenCV库简介与开发环境搭建

OpenCV 支持多种编程语言接口,包括 Python、C++、Java 等,其中 Python 接口因其简洁易用、快速开发的特点,在计算机视觉领域尤为流行。C++ 接口则更适合对性能有高要求的场景,如实时视频处理、嵌入式系统等。

3.1.1 Python/C++接口选择与配置

Python 接口安装与配置:

Python 环境下安装 OpenCV 非常简单,推荐使用 pip 安装:

pip install opencv-python

如需额外模块(如 SIFT、SURF 等专利算法),可安装扩展版本:

pip install opencv-contrib-python

安装完成后,可通过以下代码验证是否成功:

import cv2
print(cv2.__version__)
C++ 接口配置:

C++ 环境下使用 OpenCV 需要下载源码并进行编译,推荐使用 CMake 构建工具进行配置。步骤如下:

  1. 下载 OpenCV 源码: https://opencv.org/releases/
  2. 解压后使用 CMake 配置构建路径
  3. 选择目标编译器(如 Visual Studio、MinGW 等)
  4. 生成 Makefile 或项目文件,进行编译安装
  5. 将生成的库文件链接到你的 C++ 工程中

3.1.2 图像读取、显示与保存操作

OpenCV 提供了丰富的图像处理函数,其中最基本的图像读取、显示和保存操作如下:

示例:Python 实现图像读取与显示
import cv2

# 读取图像
img = cv2.imread('left_image.jpg')

# 检查是否成功读取
if img is None:
    print("图像读取失败")
else:
    # 显示图像
    cv2.imshow('Image', img)
    cv2.waitKey(0)  # 等待按键
    cv2.destroyAllWindows()  # 关闭所有窗口

    # 保存图像
    cv2.imwrite('output_image.jpg', img)

逐行解释:

  • cv2.imread() :读取图像文件,支持多种格式(jpg、png、bmp 等)
  • cv2.imshow() :在窗口中显示图像,第一个参数为窗口名
  • cv2.waitKey(0) :等待用户按键,0 表示无限等待
  • cv2.destroyAllWindows() :关闭所有创建的窗口
  • cv2.imwrite() :保存图像至指定路径

3.2 图像基础操作与矩阵处理

OpenCV 将图像视为多维数组(即矩阵),通过 NumPy(Python)或 Mat 类(C++)进行操作,这使得图像处理可以高效地进行数值运算。

3.2.1 图像通道操作与ROI提取

图像通道操作是图像处理中的基础技能之一,常用于颜色空间转换、特征提取等任务。

示例:Python 实现图像通道分离与合并
import cv2
import numpy as np

# 读取彩色图像
img = cv2.imread('color_image.jpg')

# 分离通道
b, g, r = cv2.split(img)

# 显示蓝色通道
cv2.imshow('Blue Channel', b)
cv2.waitKey(0)

# 合并通道
merged = cv2.merge((b, g, r))
cv2.imshow('Merged Image', merged)
cv2.waitKey(0)

参数说明:

  • cv2.split() :将图像按通道拆分,返回三个单通道图像
  • cv2.merge() :将多个单通道图像合并为三通道图像
ROI(Region of Interest)提取

ROI 是指图像中感兴趣的区域,常用于图像裁剪或局部处理。

# 提取图像 ROI
x, y, width, height = 100, 50, 400, 300
roi = img[y:y+height, x:x+width]

cv2.imshow('ROI', roi)
cv2.waitKey(0)

逻辑分析:

  • 图像在 NumPy 中是以数组形式存储的,因此可以通过切片操作提取子区域
  • img[y:y+height, x:x+width] 表示从 y 行到 y+height 行,x 列到 x+width 列的图像区域

3.2.2 图像类型转换与数据结构

OpenCV 中常见的图像类型包括:

图像类型 说明
CV_8UC1 8位无符号单通道图像(灰度图)
CV_8UC3 8位无符号三通道图像(彩色图)
CV_32FC1 32位浮点型单通道图像
CV_64FC3 64位浮点型三通道图像
示例:图像类型转换
# 将图像转换为灰度图
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 将图像转换为浮点型
float_img = np.float32(gray_img)

# 显示数据类型
print(float_img.dtype)  # 输出:float32

参数说明:

  • cv2.cvtColor() :用于颜色空间转换, cv2.COLOR_BGR2GRAY 表示将 BGR 图像转换为灰度图
  • np.float32() :将图像矩阵转换为浮点型,便于后续数学运算

3.3 图像几何变换与校正

几何变换是图像处理中常用的技术,包括缩放、旋转、仿射变换等。在双目视觉中,图像校正(如极线校正)尤为重要。

3.3.1 图像缩放、旋转与仿射变换

图像缩放
# 图像缩放
resized_img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)

参数说明:

  • fx fy :缩放因子,0.5 表示缩小为原来的一半
  • interpolation :插值方法, cv2.INTER_LINEAR 表示双线性插值
图像旋转
# 获取图像中心
height, width = img.shape[:2]
center = (width // 2, height // 2)

# 获取旋转矩阵
M = cv2.getRotationMatrix2D(center, angle=45, scale=1)

# 应用旋转
rotated_img = cv2.warpAffine(img, M, (width, height))
cv2.imshow('Rotated Image', rotated_img)
cv2.waitKey(0)

流程图:

graph TD
    A[原始图像] --> B[获取图像中心]
    B --> C[计算旋转矩阵]
    C --> D[应用仿射变换]
    D --> E[显示旋转图像]

3.3.2 双目相机标定与图像对齐

双目视觉系统中,图像对齐(极线校正)是立体匹配的前提。OpenCV 提供了完整的标定与校正流程。

标定流程:
  1. 使用棋盘格图像进行相机内参与外参标定
  2. 使用标定结果计算校正映射表
  3. 对左右图像进行极线校正
示例:图像极线校正(Python)
# 假设已获得标定参数
R1, R2, P1, P2, Q, _, _ = cv2.stereoRectify(cameraMatrix1, distCoeffs1,
                                            cameraMatrix2, distCoeffs2,
                                            imageSize, R, T)

# 计算映射表
map1, map2 = cv2.initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R1, P1, imageSize, cv2.CV_32FC1)

# 应用映射
rectified_img = cv2.remap(img_left, map1, map2, cv2.INTER_LINEAR)

参数说明:

  • cv2.stereoRectify() :计算双目标定后的旋转和平移矩阵
  • cv2.initUndistortRectifyMap() :生成映射表,用于图像校正
  • cv2.remap() :根据映射表对图像进行像素重映射,实现图像对齐
校正前后对比表格:
项目 校正前 校正后
极线 弯曲 水平对齐
匹配复杂度 降低
视差计算 复杂 简化为一维搜索
视觉一致性 提高

逻辑分析:

  • 校正前图像中极线不平行,匹配点搜索复杂
  • 校正后极线对齐为水平线,极大简化立体匹配的搜索过程
  • 校正提高了图像的视觉一致性,有助于提高匹配精度

总结

本章系统介绍了 OpenCV 图像处理的基础知识,包括库的安装与配置、图像的基本操作、通道处理、矩阵变换以及图像校正等核心内容。这些知识为后续的立体匹配算法实现打下了坚实的基础。掌握这些技能后,读者将能够熟练处理双目视觉系统中所需的图像预处理和几何变换操作。

4. 图像预处理技术(灰度化、归一化、去噪)

在立体匹配过程中,图像预处理是一个不可或缺的环节。良好的预处理不仅能提升匹配的精度和鲁棒性,还能减少计算复杂度,提高算法效率。本章将围绕图像预处理的三大关键技术—— 灰度化、归一化和去噪 展开详细讲解。我们将从基本原理出发,结合具体实现代码和参数说明,深入分析其在立体匹配中的作用与影响。

4.1 图像灰度化处理

在计算机视觉任务中,原始图像通常是RGB格式的彩色图像。然而,大多数立体匹配算法仅依赖于图像的亮度信息,因此将图像转换为灰度图是预处理的第一步。

4.1.1 RGB到灰度转换公式

常见的灰度化方法是基于加权平均法,最经典的是使用如下公式将RGB图像转换为灰度图像:

Y = 0.299 \times R + 0.587 \times G + 0.114 \times B

该公式反映了人眼对不同颜色通道的敏感程度,其中绿色(G)的权重最大,蓝色(B)最小。

示例代码(Python + OpenCV):
import cv2

# 读取彩色图像
img = cv2.imread('left_image.jpg')

# 转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 显示图像
cv2.imshow('Gray Image', gray_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码逻辑分析:
  • cv2.imread :读取指定路径的图像,返回一个BGR三通道的NumPy数组。
  • cv2.cvtColor :将图像从BGR颜色空间转换为灰度空间,使用的转换公式即为上述加权平均。
  • cv2.imshow :显示灰度图像窗口, cv2.waitKey(0) 表示等待按键输入关闭窗口。

4.1.2 灰度图像在立体匹配中的作用

灰度图像的主要作用包括:

作用 说明
减少计算量 单通道图像比三通道图像在匹配时计算量减少约三分之二。
提升鲁棒性 消除颜色偏差对匹配过程的影响,适用于光照变化较大的场景。
兼容性好 多数立体匹配算法如BM、SGBM等默认处理灰度图像。

在实际应用中,如双目相机的两个镜头拍摄的图像可能因白平衡不一致导致颜色偏差,此时灰度化可以有效缓解这种问题。

4.2 图像归一化技术

图像归一化是提升立体匹配鲁棒性的关键步骤,尤其是在光照不均匀或动态范围较大的场景中。

4.2.1 直方图均衡化原理与实现

直方图均衡化是一种常用的图像增强技术,其核心思想是通过拉伸图像的灰度直方图,使图像的亮度分布更均匀,从而增强图像的对比度。

示例代码(Python + OpenCV):
# 对灰度图像进行直方图均衡化
equalized_img = cv2.equalizeHist(gray_img)

# 显示结果
cv2.imshow('Equalized Image', equalized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码逻辑分析:
  • cv2.equalizeHist :对输入的单通道图像进行直方图均衡化处理,返回增强后的图像。
  • 均衡化后,图像的灰度值分布更加均匀,有助于提升匹配点的显著性。
对比分析:
图像类型 对比度 适用场景
原始灰度图像 一般 光照均匀环境
直方图均衡化图像 光照不均、暗部细节多的场景

4.2.2 图像对比度增强与光照一致性处理

除了直方图均衡化外,OpenCV还支持 自适应直方图均衡化(CLAHE) ,适用于局部对比度增强。

示例代码(CLAHE):
# 创建CLAHE对象
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))

# 应用CLAHE
clahe_img = clahe.apply(gray_img)

# 显示图像
cv2.imshow('CLAHE Image', clahe_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
参数说明:
  • clipLimit :对比度限制阈值,防止噪声被放大。
  • tileGridSize :图像被分割的块大小,通常设置为8x8或16x16。
适用场景:
  • 双目图像光照差异较大 :CLAHE可以有效提升图像的局部对比度,使左右图像的光照趋于一致。
  • 阴影或低照度区域 :增强图像的细节信息,提高匹配准确性。

4.3 图像去噪方法

在图像采集过程中,由于传感器噪声、传输干扰等原因,图像往往会受到噪声污染。噪声会严重影响匹配过程中的像素值比较,因此去噪是图像预处理的重要环节。

4.3.1 高斯滤波与中值滤波原理

高斯滤波

高斯滤波是一种线性滤波器,通过卷积核对图像进行平滑处理,适合去除高斯噪声。

# 高斯滤波
gaussian_img = cv2.GaussianBlur(gray_img, (5, 5), 0)
  • (5,5) :滤波核大小,越大平滑效果越强。
  • 0 :标准差,设为0则根据核大小自动计算。
中值滤波

中值滤波是一种非线性滤波器,适合去除椒盐噪声。

# 中值滤波
median_img = cv2.medianBlur(gray_img, 5)
  • 5 :滤波核大小,必须为奇数。
对比分析:
方法 优点 缺点 适用噪声类型
高斯滤波 平滑自然,保留边缘较好 对椒盐噪声无效 高斯噪声
中值滤波 对椒盐噪声效果好 可能模糊细节 椒盐噪声

4.3.2 小波变换与非局部均值去噪简介

OpenCV中还支持更高级的去噪算法,如 非局部均值去噪(Non-Local Means Denoising)

示例代码(NLMeans):
# 非局部均值去噪
denoised_img = cv2.fastNlMeansDenoising(gray_img, None, h=10, templateWindowSize=7, searchWindowSize=21)
参数说明:
  • h :控制去噪强度,值越大去噪越强。
  • templateWindowSize :模板窗口大小。
  • searchWindowSize :搜索窗口大小。
小波变换简介:

小波变换是一种多尺度信号分析方法,能有效分离图像中的噪声与边缘信息。虽然OpenCV未直接支持小波变换,但可通过NumPy与PyWavelets库实现。

示例代码(使用pywt库):
import pywt
import numpy as np

# 使用小波变换进行去噪
coeffs = pywt.waved2d(gray_img, 'haar')
threshold = np.std(coeffs[0]) * np.sqrt(2*np.log(gray_img.size))
coeffs = pywt.threshold(coeffs, threshold, mode='soft')
denoised = pywt.waverec2(coeffs, 'haar')
应用场景:
  • 小波变换 :适用于多尺度特征保留的去噪需求,如医学图像、卫星图像。
  • NLMeans :适合自然图像去噪,能保留纹理和边缘信息。

小结

图像预处理是立体匹配流程中至关重要的环节。通过对图像进行 灰度化 ,可以减少计算量并提升算法兼容性;通过 直方图均衡化或CLAHE ,可以增强图像对比度和光照一致性;而通过 高斯滤波、中值滤波或非局部均值去噪 ,可以有效抑制图像噪声,提高像素匹配的可靠性。

在实际应用中,预处理步骤往往需要根据具体场景进行组合和优化。例如在光照不均的双目系统中,先使用CLAHE增强对比度,再使用NLMeans去噪,最后进行灰度化处理,可以获得最佳的匹配效果。

下一章我们将深入探讨 匹配成本矩阵的构建方法 ,从视差空间的构建到成本函数的选择,进一步提升立体匹配的精度与效率。

5. 匹配成本矩阵构建

在双目立体匹配中,匹配成本矩阵的构建是整个算法流程中最核心的步骤之一。它不仅决定了后续视差计算的准确性,也直接影响最终生成的深度图质量。本章将从 成本计算方法 的选择、 数据结构设计 的优化,以及 多尺度构建策略 三个方面,深入解析匹配成本矩阵的构建过程。

5.1 成本计算方法选择

在立体匹配中,匹配成本的计算是衡量左右图像中像素或像素块相似性的重要依据。不同的成本计算方法对最终视差图的精度和鲁棒性有显著影响。常见的匹配成本计算方法包括:

  • SAD(Sum of Absolute Differences)
  • SSD(Sum of Squared Differences)
  • NCC(Normalized Cross Correlation)

5.1.1 绝对差值和(SAD)

SAD 是一种简单高效的匹配成本计算方法,其基本公式如下:

\text{SAD}(x, y, d) = \sum_{(i,j) \in W} |I_L(x+i, y+j) - I_R(x+i-d, y+j)|

其中:
- $ I_L $:左图像;
- $ I_R $:右图像;
- $ d $:当前视差值;
- $ W $:匹配窗口大小(如 5x5、7x7 等)。

SAD 的优势在于计算速度快,适合实时系统,但其对光照变化和噪声较为敏感。

示例代码:SAD 计算实现(Python + NumPy)
import numpy as np

def compute_sad(left_patch, right_patch):
    return np.sum(np.abs(left_patch - right_patch))

# 示例窗口
left_patch = np.array([[100, 105, 110],
                       [102, 107, 112],
                       [104, 109, 114]])

right_patch = np.array([[103, 108, 113],
                        [105, 110, 115],
                        [107, 112, 117]])

sad = compute_sad(left_patch, right_patch)
print("SAD Cost:", sad)

代码解析:
- compute_sad 函数接收两个图像块作为输入;
- 使用 np.abs 计算每个像素点的绝对差值;
- np.sum 累加所有差值,得到 SAD 成本;
- 此方法适用于小窗口(如 3x3、5x5)内的局部匹配。

5.1.2 平方差和(SSD)与归一化互相关(NCC)

平方差和(SSD)

SSD 与 SAD 类似,不同之处在于它使用平方代替绝对值,公式如下:

\text{SSD}(x, y, d) = \sum_{(i,j) \in W} (I_L(x+i, y+j) - I_R(x+i-d, y+j))^2

SSD 对大误差更敏感,但同样受光照变化影响较大。

归一化互相关(NCC)

NCC 是一种基于统计相关性的匹配方法,其公式如下:

\text{NCC}(x, y, d) = \frac{\sum_{(i,j) \in W} (I_L(x+i, y+j) - \bar{I_L})(I_R(x+i-d, y+j) - \bar{I_R}))}{\sqrt{\sum (I_L - \bar{I_L})^2 \sum (I_R - \bar{I_R})^2}}

其中 $ \bar{I_L} $ 和 $ \bar{I_R} $ 分别为左右图像块的均值。

NCC 对光照变化具有一定的鲁棒性,但计算复杂度高,适合对精度要求较高的场景。

方法 计算复杂度 对光照敏感 适用场景
SAD 实时系统
SSD 中等 精度要求适中
NCC 精确匹配、实验室

5.2 成本矩阵的数据结构设计

构建匹配成本矩阵的关键在于如何高效地组织和访问数据,以便后续的视差计算与优化。

5.2.1 二维视差空间构建

匹配成本矩阵通常是一个三维结构:宽度 × 高度 × 最大视差值。对于图像中的每个像素点 (x, y),我们计算其在不同视差值 d 下的匹配成本,形成一个三维成本立方体(Cost Cube)。

例如,图像尺寸为 640×480,最大视差为 64,则成本立方体大小为 640×480×64。

成本立方体结构示意(伪代码):
cost_cube = np.zeros((height, width, max_disparity), dtype=np.float32)
for y in range(height):
    for x in range(width):
        for d in range(max_disparity):
            cost_cube[y, x, d] = compute_cost(left_img[y, x], right_img[y, x - d])

参数说明:
- height :图像高度;
- width :图像宽度;
- max_disparity :最大视差值;
- compute_cost :可为 SAD、SSD 或 NCC 函数。

5.2.2 成本矩阵的优化与内存管理

由于成本立方体占用大量内存,必须进行优化设计:

  • 内存压缩 :使用 8 位整型(uint8)代替 float32 存储成本;
  • 视差范围限制 :根据场景需求限制最大视差,避免不必要的计算;
  • 按需构建 :在滑动窗口过程中动态构建局部成本矩阵;
  • 缓存机制 :利用局部窗口重叠特性,缓存前一帧的匹配结果。
示例:使用 NumPy 构建并压缩成本立方体
import numpy as np

height, width, max_disparity = 480, 640, 64
cost_cube = np.zeros((height, width, max_disparity), dtype=np.uint8)

# 模拟填充成本
for y in range(height):
    for x in range(width):
        for d in range(max_disparity):
            # 假设使用 SAD 方法
            cost = np.random.randint(0, 255)
            cost_cube[y, x, d] = cost

print("Cost Cube Memory Usage:", cost_cube.nbytes / (1024 * 1024), "MB")

输出示例:

Cost Cube Memory Usage: 19.2 MB

分析:
- 使用 uint8 类型节省了内存空间;
- 若使用 float32 ,内存将超过 100MB;
- 适用于嵌入式设备或内存受限的系统。

成本矩阵构建流程图(Mermaid)
graph TD
    A[输入左图和右图] --> B[设定最大视差]
    B --> C[初始化成本立方体]
    C --> D[遍历图像每个像素]
    D --> E[滑动窗口提取图像块]
    E --> F[计算匹配成本]
    F --> G[填入成本立方体对应位置]
    G --> H[是否完成所有视差计算]
    H -- 是 --> I[保存成本立方体]
    H -- 否 --> D

5.3 成本矩阵的多尺度构建策略

为了提高匹配的鲁棒性与效率,常采用 多尺度图像金字塔 策略,从粗到精地进行匹配。

5.3.1 多分辨率图像金字塔

图像金字塔是一种将图像按不同分辨率进行缩放的技术。在立体匹配中,我们可以先在低分辨率图像上进行粗匹配,再在高分辨率图像上进行精匹配。

构建金字塔流程:
  1. 图像缩放 :使用高斯滤波后下采样,构建不同层级的图像;
  2. 逐层匹配 :从最顶层开始计算匹配成本,逐层细化;
  3. 视差传播 :将上一层的视差结果作为当前层的初始值,减少搜索范围。
示例代码:使用 OpenCV 构建图像金字塔
import cv2
import numpy as np

def build_gaussian_pyramid(img, levels=4):
    pyramid = [img]
    for _ in range(1, levels):
        img = cv2.pyrDown(img)
        pyramid.append(img)
    return pyramid

# 读取图像
left_img = cv2.imread("left.png", 0)
pyramid = build_gaussian_pyramid(left_img, levels=4)

# 显示各层图像
for i, img in enumerate(pyramid):
    cv2.imshow(f"Level {i}", img)
cv2.waitKey(0)

参数说明:
- levels :金字塔层数;
- cv2.pyrDown() :下采样函数,每次缩小图像为原来的一半;
- pyramid :图像金字塔列表,每一层图像分辨率不同。

5.3.2 分层匹配与全局优化的结合

在多尺度策略中,匹配成本矩阵的构建可以采用分层方式进行:

  • 粗匹配层 :快速匹配,确定大致视差范围;
  • 细匹配层 :在粗匹配结果基础上,进行精细搜索;
  • 全局优化层 :结合动态规划、图割等算法,提升视差一致性。
多尺度匹配流程图(Mermaid)
graph LR
    A[原始图像] --> B[构建图像金字塔]
    B --> C[从顶层开始匹配]
    C --> D[构建当前层成本矩阵]
    D --> E[计算初始视差图]
    E --> F[下采样当前视差图]
    F --> G[作为下一层初始视差]
    G --> H[构建下一层成本矩阵]
    H --> C
    C --> I[是否完成所有层级]
    I -- 是 --> J[输出最终视差图]
示例:多尺度成本矩阵构建伪代码
def multi_scale_matching(left_pyramid, right_pyramid, max_disparity):
    disparity_map = None
    for level in reversed(range(len(left_pyramid))):
        left = left_pyramid[level]
        right = right_pyramid[level]
        if disparity_map is None:
            # 初始层匹配
            disparity_map = compute_initial_disparity(left, right, max_disparity)
        else:
            # 上采样前一层视差图
            disparity_map = cv2.resize(disparity_map, (left.shape[1], left.shape[0]))
            # 在小范围内搜索精细视差
            disparity_map = refine_disparity(left, right, disparity_map)
    return disparity_map

逻辑说明:
- reversed(range(len(...))) 表示从顶层到底层进行处理;
- 初始层使用较大搜索范围;
- 后续层基于上层结果进行局部优化;
- 提高效率的同时保持匹配精度。

通过本章的深入分析,我们掌握了匹配成本矩阵构建的三大核心要素:成本计算方法、数据结构设计与多尺度构建策略。这些内容不仅构成了立体匹配算法的基础,也为后续的代价聚合与视差优化提供了坚实的支撑。在下一章中,我们将进一步探讨如何通过代价聚合方法优化匹配成本矩阵,以提升视差图的精度与稳定性。

6. 代价聚合优化方法

代价聚合优化是立体匹配流程中的关键步骤,其核心目标是对原始的代价矩阵进行优化,以提高视差估计的准确性并减少误匹配。代价聚合可以分为 局部聚合 全局优化 两大类方法,它们在处理代价矩阵时采用不同的策略:局部方法通过滑动窗口或方向路径进行代价加权,而全局优化则通过能量函数建模并寻找最优解。此外,随着深度学习的发展,融合传统方法与神经网络的 多算法融合策略 也逐渐成为研究热点。

本章将深入解析局部代价聚合策略、全局优化方法以及多算法融合策略的核心思想、实现流程和优缺点,并结合具体代码示例和流程图进行说明。

6.1 局部代价聚合策略

局部代价聚合的基本思想是通过对原始代价矩阵中每个视差点的邻域信息进行加权,从而增强代价矩阵的鲁棒性,减少因噪声或纹理缺失导致的误匹配。常见的局部聚合方法包括 滑动窗口聚合 基于方向的代价聚合 (如 Semi-Global Matching)。

6.1.1 滑动窗口聚合方法

滑动窗口聚合是一种典型的局部聚合方式,其基本流程如下:

  1. 定义窗口大小 :通常采用 3×3 或 5×5 的窗口。
  2. 遍历图像每个像素点 ,在窗口范围内对代价进行加权求和。
  3. 加权方式 :可以是均匀权重(均值滤波),也可以使用高斯权重或自适应权重。
import numpy as np
from scipy.signal import convolve2d

def window_aggregation(cost_volume, window_size=3, weight_type='uniform'):
    """
    局部滑动窗口代价聚合函数
    :param cost_volume: 输入的代价矩阵 (H, W, D)
    :param window_size: 窗口大小,如3或5
    :param weight_type: 权重类型(uniform, gaussian)
    :return: 聚合后的代价矩阵
    """
    H, W, D = cost_volume.shape
    aggregated_volume = np.zeros_like(cost_volume)

    # 定义权重核
    if weight_type == 'uniform':
        kernel = np.ones((window_size, window_size))
    elif weight_type == 'gaussian':
        kernel = np.array([[1, 2, 1],
                           [2, 4, 2],
                           [1, 2, 1]])
    else:
        raise ValueError("Unsupported weight type")

    # 对每个视差层进行卷积
    for d in range(D):
        for c in range(cost_volume.shape[2]):
            aggregated_volume[:, :, c] = convolve2d(cost_volume[:, :, c], kernel, mode='same', boundary='symm')

    return aggregated_volume
代码逻辑分析
  • 输入 cost_volume 是一个三维矩阵,表示每个像素在不同视差下的匹配代价。
  • kernel :根据权重类型生成卷积核,用于局部加权。
  • convolve2d :对每个视差层应用二维卷积操作,实现窗口内的加权求和。
  • 输出 :优化后的代价矩阵,其每个像素点的代价是其邻域内所有点的加权平均。
参数说明
  • window_size :决定聚合窗口的大小,影响平滑程度和计算开销。
  • weight_type :权重类型影响聚合结果,高斯权重能更好地保留边缘信息。

6.1.2 基于方向的代价聚合(如Semi-Global Matching)

Semi-Global Matching(SGM)是一种经典的基于路径的局部代价聚合方法。其核心思想是在多个方向(如0°、45°、90°、135°)上进行代价累计,并将所有方向的代价进行加权求和。

SGM代价聚合流程图
graph TD
    A[输入代价矩阵] --> B[定义路径方向]
    B --> C[沿每个方向进行代价累计]
    C --> D[加权求和各方向累计代价]
    D --> E[输出优化后的代价矩阵]
示例代码(简化版)
def sgm_aggregation(cost_volume, directions=[(0,1), (1,0), (1,1), (-1,1)]):
    H, W, D = cost_volume.shape
    aggregated_volume = np.zeros_like(cost_volume)
    for dx, dy in directions:
        for y in range(H):
            for x in range(W):
                px, py = x, y
                while 0 <= px < W and 0 <= py < H:
                    for d in range(D):
                        aggregated_volume[py, px, d] += cost_volume[py, px, d]
                    px += dx
                    py += dy
    return aggregated_volume
代码分析
  • directions :定义路径方向,通常包括 4 或 8 个方向。
  • 每个方向上进行代价累计(模拟动态规划思想)。
  • 最终代价为所有方向的累加值。

6.2 全局优化方法

全局优化方法试图通过构建一个全局能量函数,并寻找使该函数最小化的视差图。这类方法通常能获得更精确的匹配结果,但计算复杂度较高。

6.2.1 动态规划(DP)在视差优化中的应用

动态规划(Dynamic Programming, DP)常用于一维路径优化问题。在立体匹配中,DP可沿图像的每一行进行视差路径优化。

DP视差优化流程图
graph TD
    A[初始化第一列代价] --> B[从左到右逐列优化]
    B --> C[计算当前列各视差点的最小累计代价]
    C --> D[记录路径回溯信息]
    D --> E[反向回溯最优视差路径]
示例代码(简化版)
def dynamic_programming_optimization(cost_volume):
    H, W, D = cost_volume.shape
    dp_table = np.zeros((H, W, D))
    path_table = np.zeros((H, W, D), dtype=int)

    # 初始化第一列
    dp_table[:, 0, :] = cost_volume[:, 0, :]

    # 从第二列开始优化
    for x in range(1, W):
        for y in range(H):
            for d in range(D):
                min_cost = np.inf
                best_d = 0
                for prev_d in range(D):
                    cost = dp_table[y, x-1, prev_d] + abs(d - prev_d)  # 平滑项
                    if cost < min_cost:
                        min_cost = cost
                        best_d = prev_d
                dp_table[y, x, d] = cost_volume[y, x, d] + min_cost
                path_table[y, x, d] = best_d

    # 回溯最优路径
    disparity_map = np.zeros((H, W))
    for y in range(H):
        last_d = np.argmin(dp_table[y, -1, :])
        disparity_map[y, -1] = last_d
        for x in reversed(range(W - 1)):
            last_d = path_table[y, x + 1, last_d]
            disparity_map[y, x] = last_d

    return disparity_map
代码分析
  • 使用动态规划进行一维路径搜索。
  • 每一步考虑前一个像素点的视差值,并计算平滑代价。
  • 最终通过回溯找到最优视差路径。

6.2.2 图割算法(Graph Cut)与信念传播(Belief Propagation)

图割算法(Graph Cut)和信念传播(Belief Propagation)是两种典型的全局优化方法。

图割算法原理

图割算法将立体匹配建模为一个图分割问题,其中每个像素点是一个图节点,边权重代表视差差异和平滑项。目标是将图划分为两个子集,使总代价最小。

信念传播(BP)原理

信念传播是一种概率图模型中的推理方法,适用于网格结构的图像。它通过在图像节点之间传递消息(message)来更新每个像素的视差概率分布。

方法对比表格
方法 优点 缺点 适用场景
动态规划 (DP) 实现简单,速度快 仅适用于一维路径优化 快速原型设计
图割 (Graph Cut) 精度高,适合全局优化 计算复杂度高,难以并行化 高精度要求的场景
信念传播 (BP) 适用于网格结构,支持概率建模 收敛速度慢,参数敏感 多视图融合、概率建模场景

6.3 多算法融合策略

随着深度学习的发展,融合传统代价聚合方法与神经网络的策略逐渐成为研究热点。通过将深度神经网络用于代价预测或优化,可以显著提升立体匹配的精度。

6.3.1 局部与全局方法结合的优劣势分析

方法组合 优势 劣势
局部 + 全局(如 SGM + BP) 兼顾效率与精度 计算资源消耗大
局部 + 深度学习(如 SGM + CNN) 提升精度,减少人工设计代价 模型训练复杂,泛化能力有限
全局 + 深度学习(如 GAN + DP) 可建模复杂代价空间 模型规模大,训练困难

6.3.2 深度学习辅助的代价优化

近年来,基于深度学习的立体匹配模型(如 PSMNet、GC-Net、StereoNet)广泛使用卷积神经网络(CNN)来构建代价体(cost volume),并引入 3D 卷积或堆叠沙漏网络进行代价优化。

示例:使用 CNN 进行代价体优化
import torch
import torch.nn as nn

class CostAggregationNet(nn.Module):
    def __init__(self):
        super(CostAggregationNet, self).__init__()
        self.conv3d_1 = nn.Conv3d(1, 32, kernel_size=3, padding=1)
        self.conv3d_2 = nn.Conv3d(32, 1, kernel_size=3, padding=1)

    def forward(self, cost_volume):
        x = cost_volume.unsqueeze(1)  # 添加通道维度
        x = torch.relu(self.conv3d_1(x))
        x = self.conv3d_2(x)
        return x.squeeze(1)
代码分析
  • 使用 3D 卷积对代价体进行空间和平滑优化。
  • conv3d_1 提取代价体的空间特征。
  • conv3d_2 输出优化后的代价体。

总结

代价聚合优化是立体匹配流程中提升匹配精度的重要环节。从局部聚合的滑动窗口与 SGM,到全局优化的 DP、图割与信念传播,再到深度学习辅助的融合策略,每种方法都有其适用场景与优劣势。实际应用中,应根据性能需求、精度目标和计算资源进行权衡选择。

在下一章中,我们将介绍视差图的生成与优化方法,进一步提升立体匹配的整体性能。

7. 视差图生成与优化

在立体匹配流程中,视差图的生成是将匹配成本矩阵转化为可视化的像素级深度信息的关键步骤。本章将详细介绍视差图的初步生成方法、后处理技术以及优化策略,确保最终输出的视差图在精度与视觉质量上达到最佳效果。

7.1 视差图的初步生成

7.1.1 成本矩阵的最小值查找

视差图的核心是每个像素点对应的视差值,而该值通常通过查找成本矩阵中的最小值来确定。以 SAD 成本矩阵为例,其构建方式如下:

import numpy as np
import cv2

def compute_sad(left_img, right_img, window_size=5, max_disparity=64):
    height, width = left_img.shape
    sad_cost = np.zeros((height, width, max_disparity), dtype=np.uint8)

    half_window = window_size // 2

    for y in range(half_window, height - half_window):
        for x in range(half_window, width - half_window):
            left_patch = left_img[y-half_window:y+half_window+1, x-half_window:x+half_window+1]
            for d in range(max_disparity):
                if x - d - half_window < 0:
                    sad_cost[y, x, d] = 255
                else:
                    right_patch = right_img[y-half_window:y+half_window+1, x-d-half_window:x-d+half_window+1]
                    sad_cost[y, x, d] = np.sum(np.abs(left_patch - right_patch))

    return sad_cost

在计算完每个像素点的成本向量后,我们通过如下方式获取视差值:

def get_disparity_map(cost_volume):
    disparity_map = np.argmin(cost_volume, axis=2)
    return disparity_map

上述代码通过 argmin 函数找到每个像素点对应的成本最小值索引,作为该像素的视差值。

7.1.2 视差映射与深度关系转换

视差值 $d$ 与深度值 $Z$ 之间存在如下几何关系:

Z = \frac{f \cdot B}{d}

其中:
- $f$:相机焦距(单位:像素)
- $B$:双目相机基线长度(单位:米)
- $d$:视差值(单位:像素)

因此,视差图可通过如下方式转换为深度图:

def disparity_to_depth(disparity_map, focal_length, baseline):
    depth_map = (focal_length * baseline) / (disparity_map + 1e-6)  # 避免除零
    return depth_map

7.2 视差图的后处理技术

7.2.1 自适应阈值处理与边缘增强

初步生成的视差图通常包含噪声和边缘模糊的问题。我们可以采用自适应阈值处理来增强边缘清晰度:

# 自适应阈值处理
disparity_normalized = cv2.normalize(disparity_map, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
_, thresholded = cv2.adaptiveThreshold(disparity_normalized, 255,
                                      cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                      cv2.THRESH_BINARY, 11, 2)

此外,使用 Sobel 算子进行边缘检测可进一步增强边缘信息:

sobel_x = cv2.Sobel(disparity_normalized, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(disparity_normalized, cv2.CV_64F, 0, 1, ksize=3)
edge_map = np.sqrt(sobel_x**2 + sobel_y**2)
edge_map = cv2.normalize(edge_map, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)

7.2.2 连通成分分析与空洞填充

由于遮挡或重复纹理,视差图中常存在“空洞”(即未匹配区域)。我们可以使用连通成分分析并结合空洞填充技术进行修复:

# 假设mask为视差图中空洞的掩膜
_, labels, stats, _ = cv2.connectedComponentsWithStats(mask, connectivity=8)

# 找出最大连通区域(假设为背景)
background_label = np.argmax(stats[1:, cv2.CC_STAT_AREA]) + 1

# 将非背景区域设为背景值(填充空洞)
filled_mask = np.where(labels != background_label, background_label, labels)
filled_mask = filled_mask.astype(np.uint8)

7.3 视差图优化策略

7.3.1 左右一致性检测(Left-Right Consistency Check)

左右一致性检测是提高视差图精度的重要手段。其核心思想是分别从左图到右图、右图到左图进行匹配,并比较两者结果是否一致:

def lr_consistency_check(left_disparity, right_disparity):
    height, width = left_disparity.shape
    consistent_disparity = np.zeros_like(left_disparity)

    for y in range(height):
        for x in range(width):
            d = left_disparity[y, x]
            if x - d >= 0 and right_disparity[y, x - d] == d:
                consistent_disparity[y, x] = d
            else:
                consistent_disparity[y, x] = 0  # 不一致则置为0(空洞)
    return consistent_disparity

7.3.2 子像素插值与结果平滑

为了提高视差图的精度,可以对视差值进行子像素插值处理。例如使用抛物线拟合方法:

def subpixel_interpolation(disparity_map, cost_volume):
    refined_disparity = np.zeros_like(disparity_map, dtype=np.float32)
    for y in range(disparity_map.shape[0]):
        for x in range(disparity_map.shape[1]):
            d = disparity_map[y, x]
            if d == 0 or d == cost_volume.shape[2] - 1:
                refined_disparity[y, x] = d
            else:
                d0 = cost_volume[y, x, d - 1]
                d1 = cost_volume[y, x, d]
                d2 = cost_volume[y, x, d + 1]
                refined_disparity[y, x] = d + (d0 - d2) / (2 * (d0 - 2 * d1 + d2))
    return refined_disparity

最后,使用中值滤波进行平滑处理:

refined_disparity = cv2.medianBlur(refined_disparity, 3)

下一章节将深入探讨如何将优化后的视差图应用于三维重建与目标定位,敬请期待。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:双目视觉立体匹配是一种通过双摄像头图像重建三维场景的技术,核心在于寻找左右图像中像素的对应关系,从而计算深度信息。本项目“litipipei_双目视觉立体匹配_”基于OpenCV库,使用Block Matching(BM)算法,实现了从双目图像输入到深度图输出的完整流程。项目内容涵盖图像预处理、匹配成本矩阵构建、代价聚合、视差计算与后处理等关键步骤。适用于机器人导航、自动驾驶、虚拟现实等场景,是学习计算机视觉和立体匹配算法的理想实践项目。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐