目录

双目视觉搭配YOLO实现3D测量

一、简介

双目(Stereo Vision)技术是一种利用两个相机来模拟人眼视觉的技术。通过对两个相机获取到的图像进行分析和匹配,可以计算出物体的深度信息。双目技术可以实现物体的三维重建、距离测量、运动分析等应用。

双目技术的原理是通过两个相机之间的基线距离来计算出物体的深度。当两个相机捕捉到的图像中存在物体时,它们会分别捕捉到该物体的两个视角。通过计算两个视角之间的差异,可以得到物体的深度信息。

YOLO(You Only Look Once)是一种目标检测算法。与传统的目标检测算法不同,YOLO算法可以在一次前向传递中完成对图像中所有目标的检测和定位。YOLO算法的特点是速度快,可以实时处理视频流,适用于实时场景下的目标检测任务。

YOLO算法采用了将输入图像分割为网格的方式,并在每个网格上预测目标的位置和类别。通过使用卷积神经网络,YOLO算法可以提取出图像中的特征,并将其应用于目标检测任务。相较于其他目标检测算法,YOLO算法具有更高的处理速度和较低的定位误差。

由于3D目标检测的数据集制作困难,本人采用双目+单目目标检测的方式 将识别和3D检测进行分开计算,成功实现3D目标检测和体积测量

3D测量

可以看出来精度还是相当高的,但是周围不能有杂物的影响

有需要合作的请私聊博主

二、双目原理

双目标定 > 立体校正(含消除畸变) > 立体匹配 > 视差计算 > 深度计算(3D坐标)计算

2.1 立体校正

2.1.1 校正目的

立体校正利用双目标定的内外参数(焦距、成像原点、畸变系数)和双目相对位置关系(旋转矩阵和平移向量),分别对左右视图进行消除畸变和行对准,使得左右视图的成像原点坐标一致、两摄像头光轴平行、左右成像平面共面、对极线行对齐。

校正前的左右相机的光心并不是平行的,两个光心的连线就叫基线,像平面与基线的交点就是极点,像点与极点所在的直线就是极线,左右极线与基线构成的平面就是空间点对应的极平面。

校正后,极点在无穷远处,两个相机的光轴平行。像点在左右图像上的高度一致。这也就是极线校正的目标。校正后做后续的立体匹配时,只需在同一行上搜索左右像平面的匹配点即可,能使效率大大提高。

2.1.2 校正方法

实验利用OpenCV中的stereoRectify()函数实现立体校正,stereoRectify()函数内部采用的是Bouguet的极线校正算法,Bouguet算法步骤:

1、将右图像平面相对于左图像平面的旋转矩阵分解成两个矩阵Rl和Rr,叫做左右相机的合成旋转矩阵

2、将左右相机各旋转一半,使得左右相机的光轴平行。此时左右相机的成像面达到平行,但是基线与成像平面不平行

3、构造变换矩阵Rrect使得基线与成像平面平行。构造的方法是通过右相机相对于左相机的偏移矩阵T完成的

4、通过合成旋转矩阵与变换矩阵相乘获得左右相机的整体旋转矩阵。左右相机坐标系乘以各自的整体旋转矩阵就可使得左右相机的主光轴平行,且像平面与基线平行

5、通过上述的两个整体旋转矩阵,就能够得到理想的平行配置的双目立体系图像。校正后根据需要对图像进行裁剪,需重新选择一个图像中心,和图像边缘从而让左、右叠加部分最大

校正后的效果图:

2.1.2 相关代码

复制代码
def getRectifyTransform(height, width, config):
    # 读取内参和外参
    left_K = config.cam_matrix_left
    right_K = config.cam_matrix_right
    left_distortion = config.distortion_l
    right_distortion = config.distortion_r
    R = config.R
    T = config.T

    # 计算校正变换
    R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(left_K, left_distortion, right_K, right_distortion,
                                                      (width, height), R, T, alpha=0)
    map1x, map1y = cv2.initUndistortRectifyMap(left_K, left_distortion, R1, P1, (width, height), cv2.CV_32FC1)
    map2x, map2y = cv2.initUndistortRectifyMap(right_K, right_distortion, R2, P2, (width, height), cv2.CV_32FC1)

    return map1x, map1y, map2x, map2y, Q


# 畸变校正和立体校正
def rectifyImage(image1, image2, map1x, map1y, map2x, map2y):
    rectifyed_img1 = cv2.remap(image1, map1x, map1y, cv2.INTER_AREA)
    rectifyed_img2 = cv2.remap(image2, map2x, map2y, cv2.INTER_AREA)

    return rectifyed_img1, rectifyed_img2

立体匹配和视差计算

立体匹配也称作视差估计,立体匹配可划分为四个步骤:匹配代价计算、代价聚合、视差计算和视差优化。立体校正后的左右两幅图像得到后,匹配点是在同一行上的,可以使用OpenCV中的BM算法或者SGBM算法计算视差图。由于SGBM算法的表现要远远优于BM算法,因此采用SGBM算法获取视差图。在立体匹配生成视差图后,可以对视差图进行后处理,如滤波,空洞填充等方法,从而改善视差图的视觉效果

相关代码

复制代码
def stereoMatchSGBM(left_image, right_image, down_scale=False):
    # SGBM匹配参数设置
    if left_image.ndim == 2:
        img_channels = 1
    else:
        img_channels = 3
    blockSize = 3
    paraml = {'minDisparity': 0,
              'numDisparities': 64,
              'blockSize': blockSize,
              'P1': 8 * img_channels * blockSize ** 2,
              'P2': 32 * img_channels * blockSize ** 2,
              'disp12MaxDiff': 1,
              'preFilterCap': 63,
              'uniquenessRatio': 15,
              'speckleWindowSize': 100,
              'speckleRange': 1,
              'mode': cv2.STEREO_SGBM_MODE_SGBM_3WAY
              }

    # 构建SGBM对象
    left_matcher = cv2.StereoSGBM_create(**paraml)
    paramr = paraml
    paramr['minDisparity'] = -paraml['numDisparities']
    right_matcher = cv2.StereoSGBM_create(**paramr)

    # 计算视差图
    size = (left_image.shape[1], left_image.shape[0])
    if down_scale == False:
        disparity_left = left_matcher.compute(left_image, right_image)
        disparity_right = right_matcher.compute(right_image, left_image)
    else:
        left_image_down = cv2.pyrDown(left_image)
        right_image_down = cv2.pyrDown(right_image)
        factor = left_image.shape[1] / left_image_down.shape[1]

        disparity_left_half = left_matcher.compute(left_image_down, right_image_down)
        disparity_right_half = right_matcher.compute(right_image_down, left_image_down)
        disparity_left = cv2.resize(disparity_left_half, size, interpolation=cv2.INTER_AREA)
        disparity_right = cv2.resize(disparity_right_half, size, interpolation=cv2.INTER_AREA)
        disparity_left = factor * disparity_left
        disparity_right = factor * disparity_right

    # 真实视差(因为SGBM算法得到的视差是×16的)
    trueDisp_left = disparity_left.astype(np.float32) / 16.
    trueDisp_right = disparity_right.astype(np.float32) / 16.

    return trueDisp_left, trueDisp_right

深度计算

得到视差图后,计算像素深度值,公式如下:

depth = ( f * baseline) / disp

其中,depth表示深度图;f表示归一化的焦距,也就是内参中的fx; baseline是两个相机光心之间的距离,称作基线距离;disp是视差值

实验直接利用opencv中的cv2.reprojectImageTo3D()函数计算深度图,代码如下

复制代码
def getDepthMapWithQ(disparityMap: np.ndarray, Q: np.ndarray) -> np.ndarray:
    points_3d = cv2.reprojectImageTo3D(disparityMap, Q)
    depthMap = points_3d[:, :, 2]
    reset_index = np.where(np.logical_or(depthMap < 0.0, depthMap > 65535.0))
    depthMap[reset_index] = 0
    return depthMap.astype(np.float32)
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
YiHanXii5 小时前
使用glb作为react的3D组件
javascript·react.js·3d
渲染101专业云渲染9 小时前
3ds Max 2026 新功能全面解析
3d·云计算·blender·maya·houdini
Hanqi.i1 天前
GraphMLP: A Graph MLP-Like Architecture for 3D Human Pose Estimation
3d
go54631584651 天前
Python 中接入 SolidWorks API 来抓取 3D 模型进行选择
开发语言·python·3d
康谋自动驾驶1 天前
多模态自动驾驶混合渲染HRMAD:将NeRF和3DGS进行感知验证和端到端AD测试
数码相机·3d·自动驾驶
Fulima_cloud1 天前
3D编辑器:开启虚拟世界的创意大门
3d·编辑器
放羊郎1 天前
不同YOLO版本之间对比关系
yolo·yolov5·识别·yolo不同版本对比
FL16238631291 天前
基于yolov11的棉花品种分类检测系统python源码+pytorch模型+评估指标曲线+精美GUI界面
人工智能·pytorch·yolo
开心小老虎1 天前
纯HTML+CSS实现3D空间正方体旋转
前端·css·3d·html
德宏大魔王(AI自动回关)1 天前
YoloV8训练和平精英人物检测模型
人工智能·深度学习·yolo