OpenCV双目测距项目源代码详解

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

简介:OpenCV是一个广泛使用的计算机视觉库,特别适用于立体视觉、深度感知和三维重建等应用。在本项目中,我们将探讨如何使用OpenCV中的双目测距技术,通过两个摄像头捕获图像并计算场景中物体的距离。这个项目包含了完整的源代码,涵盖了预处理、特征匹配、立体匹配、深度图和距离计算、后处理以及可视化等关键环节。通过这个项目,你可以深入了解双目测距的实现流程,并应用这些知识于自动驾驶、无人机避障和室内机器人导航等领域。 opencv双目测距(附源代码)源码.zip

1. OpenCV在计算机视觉中的应用

在当今的IT行业中,计算机视觉作为一个迅速发展的领域,对算法和软件工具的需求极高。OpenCV(开源计算机视觉库)作为一个功能强大的计算机视觉和机器学习软件库,为这一领域提供了丰富的工具和函数。它不仅支持多种编程语言,如C++, Java, Python等,还支持各种平台,从PC到移动设备,其应用范围之广,使得它成为了该行业的首选工具。

1.1 OpenCV的基本功能介绍

OpenCV的主要功能包括图像处理、视频处理、特征检测、图像识别、机器学习等方面。对于图像处理,它提供了滤波、边缘检测、形态学操作等多种功能。在视频处理方面,它支持视频文件的读写、实时视频流的处理以及运动分析等。特别地,OpenCV在特征检测和图像识别方面,提供了SIFT、SURF、ORB等多种特征检测算法,极大地方便了计算机视觉研究和开发者的使用。

1.2 OpenCV在行业中的应用

随着技术的不断进步,OpenCV的应用也越来越广泛。例如,它在自动驾驶汽车、机器人导航、三维重建、生物特征识别、动作识别等领域都发挥了重要的作用。在自动驾驶技术中,OpenCV用于实时处理车辆的摄像头图像,识别道路标识、行人和其他车辆,从而实现安全导航。在三维重建方面,它能够从一组二维图像中恢复出物体的三维结构,这在虚拟现实和游戏开发中具有重要意义。

在本章中,我们将深入探讨OpenCV的基本原理和功能,并结合具体实例,展示其在计算机视觉领域的各种应用。在后续章节中,我们将进一步探讨OpenCV在具体技术领域中的应用细节,例如双目测距、立体匹配算法、深度图生成等。

2. 双目测距技术原理

2.1 双目视觉系统的构成

双目视觉系统,简而言之,是由两个摄像头模拟人类的双眼系统,通过分析从两个不同角度获取的图像之间的差异,来推算物体的深度信息。为了精确实现这一点,系统需要经过摄像机标定与校正以及立体图像获取这两个步骤。

2.1.1 摄像机标定与校正

摄像机标定是双目测距技术中的关键步骤之一,它涉及确定摄像机的内参矩阵、畸变系数等参数。这些参数对于后续的立体校正和视差图计算至关重要。校正过程包括消除镜头畸变和校准两个摄像机的相对位置和方向。OpenCV库提供了一系列函数来帮助完成标定和校正过程。

代码示例:

import numpy as np
import cv2

# 设置棋盘格的大小和角点的数量
chessboard_size = (6, 9)
square_size = 1.0  # 假设单位为米

# 3D世界坐标点
objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
objp = objp * square_size

# 存储所有图像对象点和图像点的数组
objpoints = []  # 3D点
imgpoints = []  # 2D点

# 检测棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)

# 添加对象点,图像点
if ret == True:
    objpoints.append(objp)
    imgpoints.append(corners)

# 计算摄像机内参和畸变系数
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

2.1.2 立体图像获取

在摄像机校正后,需要从两个校正过的摄像机中获取图像。这些图像需要具备足够的重叠区域,使得立体匹配算法可以找到对应的特征点。通常情况下,通过同步触发两个摄像机来实现这一目标。

代码示例:

# 假设已经通过OpenCV的VideoCapture获取到了左右两个摄像机的帧
ret, frame1 = left_cap.read()  # 左摄像机帧
ret, frame2 = right_cap.read() # 右摄像机帧

# 确保两个摄像机获取的帧大小相同
frame1 = cv2.resize(frame1, (frame_size_width, frame_size_height))
frame2 = cv2.resize(frame2, (frame_size_width, frame_size_height))

立体图像的获取不仅需要保证图像质量,还需要确保两个摄像机之间的几何关系已经被准确标定,以便之后计算视差图。

2.2 视差图的生成与解析

2.2.1 视差概念的引入

视差是双目视觉系统中衡量同一个物体在左右摄像机图像中的水平位置差异。视差图是根据立体图像对生成的,它直观地表示了图像中每一点的视差大小。通过分析视差图,可以得到物体的深度信息,进而用于测距。

2.2.2 视差计算方法

计算视差的方法多种多样,传统的块匹配方法(Block Matching)和较为先进的半全局匹配算法(Semi-Global Matching, SGM)是其中的代表。SGM算法通过优化一个全局能量函数来获得更为平滑和精确的视差图。

代码示例:

# 使用OpenCV中的StereoBM或StereoSGBM算法进行视差图计算
# 这里展示使用StereoBM算法
bm = cv2.StereoBM_create(numDisparities=16, blockSize=15)
disparity = bm.compute(frame1, frame2)

视差图的计算是双目视觉技术中最为复杂的部分之一,涉及到优化理论、概率统计和图像处理等多方面的知识。

在下一章节中,我们将进一步探讨如何从视差图中解析深度信息,并生成深度图。这一步骤对于双目测距技术至关重要,因为深度图能直观地展示场景的三维结构信息。

3. 视差计算和深度感知

3.1 视差图的求取

3.1.1 图像预处理

在进行视差图的求取之前,图像预处理是十分关键的一步,它能够有效提升视差计算的准确度。预处理主要包括去除图像噪声、图像增强和对比度调整等步骤。

噪声的存在会影响后续的特征点检测和匹配,从而降低立体匹配的质量。常用的去噪算法包括高斯滤波、中值滤波和双边滤波。其中,高斯滤波通过在图像上应用高斯核函数来平滑图像,减少高频噪声,适合处理高斯噪声。中值滤波是通过取邻域像素的中值来替代当前像素值,能够有效去除椒盐噪声,并保持图像边缘信息。双边滤波则结合了空域信息和像素值信息,能够在滤除噪声的同时保持边缘的锐利度。

图像增强则是一种提高图像可观察性的技术,常用于改善图像的局部或全局对比度,或者调整图像的色彩平衡。常用的图像增强技术有直方图均衡化和直方图规定化。直方图均衡化通过拉伸图像的直方图,使得图像的对比度得到增强;直方图规定化则是根据目标图像的直方图来调整源图像的直方图,使得增强后的图像符合预设的直方图分布。

以下为高斯滤波去噪和直方图均衡化的Python代码示例:

import cv2
import numpy as np

# 读取图像
image = cv2.imread('left_image.jpg', 0)

# 高斯滤波去噪
blurred_image = cv2.GaussianBlur(image, (5, 5), 0)

# 直方图均衡化增强图像
equalized_image = cv2.equalizeHist(blurred_image)

# 显示原始图像和增强后的图像
cv2.imshow('Original Image', image)
cv2.imshow('Blurred and Equalized Image', equalized_image)

# 等待按键后退出
cv2.waitKey(0)
cv2.destroyAllWindows()

这段代码首先读取一个左视图图像,并使用高斯滤波器对图像进行去噪处理。随后,对去噪后的图像进行直方图均衡化以增强图像对比度。最终,分别显示原始图像和处理后的图像以供观察效果。

3.1.2 视差图获取算法

获取视差图是双目视觉系统中至关重要的一步。视差图代表了同一场景点在左右视图中的水平位置差异。获取视差图的算法主要有块匹配(Block Matching, BM)、半全局匹配(Semi-Global Matching, SGM)以及图割(Graph Cut)等。

块匹配算法是一种局部匹配策略,它将左视图中的一个块(Block)与右视图中相同大小的块在某一搜索范围搜索最佳匹配。其主要步骤包括块的提取、相似度计算、最佳匹配点的寻找以及视差的计算。

半全局匹配算法则是结合了局部和全局的匹配策略。它在块匹配的基础上,考虑了整幅图像的连续性和平滑性,通过设定代价聚合的方式,使得匹配结果在图像区域内具有更优的平滑性。SGM算法通常通过动态规划来最小化整体的能量函数,从而得到更加精确的视差图。

图割算法利用图像分割的思想,通过定义一幅图的最优切割来解决视差计算问题。它将像素之间的相似度或不相似度作为图中的权重,然后通过最小化能量函数来得到最优的视差分配。

下面是一个使用OpenCV实现的块匹配算法的简单示例:

import cv2
import numpy as np

# 读取图像对
left_image = cv2.imread('left_image.jpg', 0)
right_image = cv2.imread('right_image.jpg', 0)

# 创建ORB检测器对象
orb = cv2.ORB_create()

# 关键点检测与描述符提取
kp1, des1 = orb.detectAndCompute(left_image, None)
kp2, des2 = orb.detectAndCompute(right_image, None)

# 创建BFMatcher对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# 进行匹配
matches = bf.match(des1, des2)

# 根据距离排序
matches = sorted(matches, key=lambda x: x.distance)

# 输出匹配结果
for i, match in enumerate(matches[:10]):
    print(f"Match {i}: Distance: {match.distance}")

# 绘制前10个匹配点
img3 = cv2.drawMatches(left_image, kp1, right_image, kp2, matches[:10], None, flags=2)
cv2.imshow('Matches', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

这段代码首先读取两幅图像,并使用ORB特征检测器来提取特征点和描述符。之后,使用BFMatcher进行特征点的匹配,并输出匹配结果的前10个。最后,使用 drawMatches 函数在图像上绘制这些匹配的特征点。

3.2 深度信息的解析

3.2.1 视差到深度的转换

视差图提供了一个场景中不同物体点在左右图像间的相对位置差异信息,而深度信息是实际的物理距离,是物体到相机的实际距离。视差值和深度值之间的转换关系可以通过以下公式来描述:

Z = (f * B) / d

其中, Z 表示深度值, f 表示相机焦距, B 表示两相机之间的基线距离(即左右相机镜头中心点之间的距离), d 表示视差值。

这个公式的含义是,通过已知的相机参数(焦距、基线距离)和图像上对应点的视差值,就可以计算得到实际的深度信息。在实际应用中,需要确保相机标定准确,以保证深度信息的准确性。

3.2.2 深度图的生成

深度图是基于视差图通过上述转换关系生成的。深度图中的每个像素值对应于原始图像中相应像素点的深度信息,通常以灰度值的形式表示。深度图的生成流程主要包括以下几个步骤:

  1. 获取左右图像对应的视差图。
  2. 根据视差图和相机参数计算深度图。
  3. 将深度值映射到灰度值,生成深度图。
  4. 可以通过调整映射范围或者应用非线性变换,优化深度图的显示效果。

生成深度图的代码示例:

import numpy as np

# 假设我们已经获得了左右视图的视差值,并存储在left_disp 和 right_disp变量中
# 这里我们只处理单色图,深度图将是一个灰度值图

# 以下参数需要通过相机标定获得
focal_length = 700  # 焦距,单位:像素
baseline = 0.06     # 基线距离,单位:米

# 创建深度图初始化为零
depth_map = np.zeros(left_image.shape, dtype=np.float32)

# 遍历图像中的每个像素点
for v in range(left_image.shape[0]):
    for u in range(left_image.shape[1]):
        # 计算深度
        disp = left_disp[v, u]  # 假设left_disp是已经计算好的视差图
        if disp != 0:
            Z = (focal_length * baseline) / disp
            depth_map[v, u] = Z

# 显示深度图
cv2.imshow('Depth Map', depth_map / np.max(depth_map))  # 归一化到[0, 1]以便显示
cv2.waitKey(0)
cv2.destroyAllWindows()

上述代码中,我们首先定义了焦距和基线距离的参数,然后初始化了一个与输入图像大小相同的深度图。接着遍历图像中的每个像素点,根据视差值计算其对应的深度值,并将这些深度值存储在深度图中。最后,将深度图归一化并显示出来。注意,这段代码假设视差图已经计算出来且存储在变量 left_disp 中。

接下来,为深度图生成提供代码优化和调试技巧的子章节内容。

4. 特征检测与匹配方法

4.1 特征检测技术概述

4.1.1 SIFT特征检测

尺度不变特征变换(Scale-Invariant Feature Transform, SIFT)是一种被广泛使用的特征检测算法。它能够检测出图像中的局部特征点,并具有尺度不变性和旋转不变性。SIFT特征检测通常包括以下几个步骤:

  1. 尺度空间极值检测 :在不同尺度空间中寻找图像的极值点,构建尺度空间。
  2. 关键点定位 :精确定位极值点,去除低对比度的关键点和边缘响应不稳定的点。
  3. 方向赋值 :为每个关键点赋予一个或多个方向参数,使算法具有旋转不变性。
  4. 关键点描述符生成 :为每个关键点生成描述符,描述符是基于关键点邻域的图像信息。

SIFT的Python实现示例如下:

import cv2
import numpy as np

# 读取图片
image = cv2.imread('example.jpg', 0)

# 初始化SIFT检测器
sift = cv2.SIFT_create()

# 寻找关键点和描述符
keypoints, descriptors = sift.detectAndCompute(image, None)

# 绘制关键点
cv2.drawKeypoints(image, keypoints, image)

# 显示图片
cv2.imshow('SIFT', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.1.2 SURF特征检测

加速鲁棒特征(Speeded-Up Robust Features, SURF)是另一种高效的特征检测算法。与SIFT相比,SURF在保证特征点检测性能的同时,提高了运算速度。SURF的关键步骤有:

  1. 尺度空间的构建 :使用快速盒滤波器构建Hessian矩阵的近似值,快速检测尺度空间极值。
  2. 关键点定位与过滤 :与SIFT类似,但使用Hessian矩阵作为关键点定位的依据,计算速度快。
  3. 描述符生成 :生成基于Haar小波的描述符,用于表征关键点的局部区域特征。

以下是SURF特征检测的Python代码:

import cv2

# 读取图片
image = cv2.imread('example.jpg', 0)

# 初始化SURF检测器
surf = cv2.xfeatures2d.SURF_create()

# 寻找关键点和描述符
keypoints, descriptors = surf.detectAndCompute(image, None)

# 绘制关键点
cv2.drawKeypoints(image, keypoints, image)

# 显示图片
cv2.imshow('SURF', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2 特征匹配算法实例

4.2.1 ORB特征匹配

Oriented FAST and Rotated BRIEF(ORB)是一种快速的特征点检测和描述算法。ORB结合了FAST关键点检测器和BRIEF描述符,并加入了旋转和尺度不变性。ORB的关键点检测和描述符生成过程如下:

  1. 关键点检测 :使用FAST算法检测角点。
  2. 关键点方向 :为关键点分配方向,使用图像金字塔来实现尺度不变性。
  3. 描述符生成 :使用BRIEF描述符,并增加旋转不变性。

以下是使用ORB进行特征匹配的Python代码:

import cv2
import numpy as np

# 读取图片
image1 = cv2.imread('image1.jpg', 0)
image2 = cv2.imread('image2.jpg', 0)

# 初始化ORB检测器
orb = cv2.ORB_create()

# 寻找关键点和描述符
keypoints1, descriptors1 = orb.detectAndCompute(image1, None)
keypoints2, descriptors2 = orb.detectAndCompute(image2, None)

# 创建匹配器
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# 进行匹配
matches = matcher.match(descriptors1, descriptors2)

# 按照距离排序
matches = sorted(matches, key=lambda x: x.distance)

# 绘制前N个匹配项
img_matches = cv2.drawMatches(image1, keypoints1, image2, keypoints2, matches[:10], None, flags=2)

# 显示图片
cv2.imshow('Matches', img_matches)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2.2 特征匹配的效果评估

特征匹配的效果评估通常涉及以下几个方面:

  1. 匹配数量 :匹配点的多少可以反映出两幅图像之间有多少相似之处。
  2. 匹配质量 :通过匹配点对之间的距离来评价匹配质量,距离越小表示匹配越准确。
  3. 重投影误差 :对于三维重建等应用,匹配点对在三维空间的重投影误差也是重要的评价指标。

评估特征匹配的Python代码如下:

# 计算匹配点对的重投影误差
errors = []
for m in matches:
    # 假设我们已经有了匹配点对应的实际三维坐标
    p1 = np.array(keypoints1[m.queryIdx].pt)
    p2 = np.array(keypoints2[m.trainIdx].pt)
    p1_true = np.array([100, 100])  # 举例的三维坐标点
    p2_true = np.array([200, 200])
    # 从图片坐标转换到三维空间坐标
    p1_3d = np.linalg.inv(camera_matrix).dot(np.append(p1, 1))
    p2_3d = np.linalg.inv(camera_matrix).dot(np.append(p2, 1))
    # 计算重投影误差
    error = np.linalg.norm(p1_3d[:2] - p1_true) + np.linalg.norm(p2_3d[:2] - p2_true)
    errors.append(error)

# 输出平均重投影误差
print("Mean Reprojection Error: ", np.mean(errors))

通过上述方法,我们可以对特征匹配的效果进行定性和定量的评估,为后续的三维重建等任务打下基础。

5. 立体匹配算法

5.1 立体匹配算法基础

立体匹配算法是双目测距技术中极为重要的一环,它通过分析来自不同视角的图像对,计算对应点之间的视差,从而获得场景的三维结构信息。在计算机视觉领域,立体匹配技术已经广泛应用在自动驾驶、机器人导航、三维重建等多个领域。

5.1.1 全局立体匹配算法

全局立体匹配算法(Global Stereo Matching Algorithms)试图找到一个最优的视差图,这个视差图满足所有的约束条件,并且使得能量函数最小化。通常来说,这类算法的精确度较高,但计算开销也较大。

一个典型的全局立体匹配算法是图割(Graph Cut)算法,该算法将立体匹配问题建模为一个能量最小化问题,并利用最大流最小割定理来找到最小能量解。图割算法的关键在于定义一个合适的能量函数,该函数包含数据项和平滑项。数据项用于确保匹配结果与图像信息一致,而平滑项则用来保证视差图的连贯性。

5.1.2 局部立体匹配算法

与全局算法相比,局部立体匹配算法(Local Stereo Matching Algorithms)则关注于独立于其他像素的局部区域,并在局部区域内寻找最佳匹配。这类算法的计算速度较快,但是准确度往往不如全局算法。

经典的局部匹配算法包括块匹配(Block Matching)算法和半全局匹配(Semi-Global Matching,SGM)算法。块匹配算法是最简单的匹配策略之一,它通过在参考图像和目标图像中移动一个大小相同的窗口来进行匹配计算。然而,由于块匹配可能无法处理遮挡区域和纹理缺乏区域,SGM算法应运而生,通过引入多个一维路径上的匹配代价聚合,来提高匹配的准确度和鲁棒性。

5.2 高级立体匹配技术

随着计算能力的提升以及算法研究的深入,出现了更多高效的立体匹配算法。这些算法在保持较高精度的同时,优化了计算过程,降低了资源消耗。

5.2.1 半全局匹配算法(SGBM)

半全局匹配算法(Semi-Global Matching,SGBM)是SGM算法的一个变种,它在全局匹配和局部匹配之间取得了一个平衡。SGBM算法通过在一个或多个方向上应用动态规划技术,来计算一系列路径上的累计代价。这些代价通过代价聚合来平滑视差图,最终得到更精确的视差估计。

SGBM算法的一个关键优势是其对视差图边缘的处理能力,相较于传统的区域匹配方法,SGBM能更好地保留边缘信息,减少视差不连续的问题。其代价函数通常包括数据项和平滑项,数据项基于像素强度差,而平滑项通过一维路径上的代价聚合来实现。

以下是使用SGBM算法的Python代码示例,采用OpenCV库进行立体匹配计算:

import cv2
import numpy as np

# 使用OpenCV的SGBM算法获取深度信息
sgbm = cv2.StereoSGBM_create(
    minDisparity=0, # 最小视差值
    numDisparities=16*5, # 视差范围
    blockSize=3, # 匹配块大小
    P1=8 * 3 * 3**2, # 平滑参数1
    P2=32 * 3 * 3**2, # 平滑参数2
    disp12MaxDiff=1, # 左右视差最大差异值
    uniquenessRatio=10, # 唯一性比率
    speckleWindowSize=100, # 噪点窗口大小
    speckleRange=32 # 噪点范围
)

# left和right为预处理过的左右图像
disparity = sgbm.compute(left_image, right_image)

# 使用CV2.normalize进行视差图归一化
disparity_normalized = cv2.normalize(disparity, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

在这段代码中,我们首先创建了一个SGBM对象,其中设置了一些关键的参数,如视差范围、块大小、平滑项的权重等。这些参数对算法的最终效果有重要影响,需要根据实际应用进行调整。之后,我们使用 compute 方法对左右图像进行视差计算,并对结果进行归一化处理,以便于显示和进一步分析。

5.2.2 块匹配算法(BM)

块匹配算法(Block Matching, BM)是一种局部立体匹配算法,其核心思想是将一个窗口(block)从一个图像移动到另一个图像上,计算窗口内像素与另一图像对应区域的相似度,并找到最佳匹配位置。

BM算法的优点在于其简单和快速性,特别适合在资源有限的环境下使用。然而,BM算法在处理遮挡和重复纹理时效果不佳,容易产生不连续的视差图。此外,块大小的选择对匹配结果的影响很大,需要仔细选择以达到最佳效果。

以下是一个BM算法的简单Python代码示例,同样使用OpenCV库实现:

# 使用OpenCV的BM算法获取深度信息
bm = cv2.BM_create()
disparity = bm.compute(left_image, right_image)
disparity_normalized = cv2.normalize(disparity, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

与SGBM算法类似,BM算法同样通过 compute 方法计算视差。在实际应用中,BM算法的性能和准确性通常低于SGBM算法,特别是在复杂的三维场景中,但是由于其计算速度较快,因此在实时性要求较高的场景下仍然有其应用价值。

6. 深度图和距离计算

在前几章节中,我们了解了双目测距技术的原理,并探讨了如何生成视差图和深度信息。本章,我们将深入分析深度图的生成过程,并学习如何计算物体间的距离,最后讨论如何对测距结果进行校验。

6.1 深度图的生成与分析

6.1.1 从视差图到深度图

生成深度图是将视差图像转化为深度信息的关键步骤。深度图中每个像素的值表示从摄像机到相应场景点的距离。转换公式如下:

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

其中: - (Z) 是深度值。 - (f) 是摄像机的焦距。 - (B) 是摄像机间的基线距离(即两摄像机光心间的距离)。 - (d) 是视差值,即同一场景点在左右图像中的水平位置差。

在实际应用中,需要对整个视差图进行逐像素处理,以生成完整的深度图。然而,并不是所有的视差值都能直接用于深度转换,因为视差图中可能包含无效值,如视差计算未能成功的地方。因此,通常需要通过滤波等方法来优化视差图。

6.1.2 深度图的优化处理

深度图的优化处理是通过平滑算法来消除深度图中的噪声,并尽可能地保持边缘信息。常见的深度图优化方法包括双边滤波、联合滤波等。

例如,双边滤波不仅考虑了像素间的空间距离,还考虑了像素间的强度差异,使得滤波结果既平滑了噪声,又保护了边缘信息。联合滤波则是一种更先进的方法,它将视差图中的局部连贯性和平滑性同时考虑进来。

import cv2

# 假设 disparity_map 是我们已经得到的视差图
depth_map = cv2.reprojectImageTo3D(disparity_map, Q)

# 双边滤波优化深度图
filtered_depth_map = cv2.bilateralFilter(depth_map, 9, 75, 75)

# 显示深度图
cv2.imshow('Depth Map', filtered_depth_map / np.max(filtered_depth_map))
cv2.waitKey(0)
cv2.destroyAllWindows()

在这段代码中, reprojectImageTo3D 函数基于四元矩阵 Q 将视差图转换为深度图。之后,我们使用 bilateralFilter 对深度图进行双边滤波优化。

6.2 测距结果的计算与校验

6.2.1 距离的计算方法

一旦深度图生成,计算特定点到摄像机的距离变得直接。具体计算方法就是取深度图中对应点的深度值。不过,如果场景中存在多个物体,测量特定物体的距离还需要将深度图分割成不同的区域。

例如,我们可以使用阈值分割方法将深度图分割成前景和背景:

_, thresholded_depth = cv2.threshold(filtered_depth_map, 0.5, 1.0, cv2.THRESH_BINARY)

# 连通区域分析,找出特定物体
labels, counts = np.unique(thresholded_depth, return_counts=True)
max_label = labels[np.argmax(counts[1:])]  # 排除背景
object_mask = (thresholded_depth == max_label)

# 计算物体中心点
object_center = cv2.mean(filtered_depth_map, mask=object_mask)[:3]

这里,我们首先对深度图进行二值化处理,然后利用连通区域分析找出面积最大的物体。最后,使用 cv2.mean 计算选定区域的中心点深度。

6.2.2 实际应用中的误差校正

在实际应用中,由于摄像机标定误差、成像噪声、物体表面特性等因素,测距结果往往存在误差。因此,误差校正显得尤为重要。

误差校正通常包括以下几个方面:

  • 摄像机标定误差校正:通过摄像机标定获取更准确的摄像机参数。
  • 环境因素校正:如照明条件、温度影响等。
  • 后处理算法校正:使用后处理算法进一步减小测量误差。

例如,我们可以对摄像机标定参数进行优化,重新标定摄像机,或使用更复杂的深度校正算法来提高深度测量的精度。

在代码层面,我们可以:

# 假设 Q 是摄像机标定参数矩阵
# 对 Q 进行优化,Q 是一个 4x4 的矩阵,包含了摄像机的内参和外参
# 优化过程可能涉及复杂的数学运算和迭代算法,这里只展示伪代码
optimized_Q = optimize_camera_parameters(Q)

优化后的摄像机参数可以用来提高后续深度计算的准确性。

在本章中,我们介绍了深度图的生成与分析方法,以及如何对测距结果进行计算和校验。下一章我们将探讨如何在源代码中应用图像预处理、后处理及可视化技术。

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

简介:OpenCV是一个广泛使用的计算机视觉库,特别适用于立体视觉、深度感知和三维重建等应用。在本项目中,我们将探讨如何使用OpenCV中的双目测距技术,通过两个摄像头捕获图像并计算场景中物体的距离。这个项目包含了完整的源代码,涵盖了预处理、特征匹配、立体匹配、深度图和距离计算、后处理以及可视化等关键环节。通过这个项目,你可以深入了解双目测距的实现流程,并应用这些知识于自动驾驶、无人机避障和室内机器人导航等领域。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值