【双目视觉】双目立体匹配

这篇具有很好参考价值的文章主要介绍了【双目视觉】双目立体匹配。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、双目立体匹配算法

在opencv中用的比较多的双目立体匹配算法有两种:BM和SGBM。SGBM是BM立体匹配算法的优化版,属于半全局匹配,相对于BM花的时间要更多,但效果优于BM。本文使用的是SGBM半全局匹配方式。
步骤:
1.打开相机,获取到左目和右目的图像;
2.矫正畸变;
3.图像灰度化;
4.立体匹配,输出结果。

代码步骤

导入所需的第三方库

import cv2
import numpy as np
# 畸变矫正脚本
import camera_config

矫正畸变

left_remap = cv2.remap(imgLeft, camera_config.left_map1, camera_config.left_map2, cv2.INTER_LINEAR)
right_remap = cv2.remap(imgRight, camera_config.right_map1, camera_config.right_map2, cv2.INTER_LINEAR)

灰度化

imgL_gray = cv2.cvtColor(left_remap, cv2.COLOR_BGR2GRAY)
imgR_gray = cv2.cvtColor(right_remap, cv2.COLOR_BGR2GRAY)

立体匹配

### 设置参数
#块大小必须为奇数(3-11)
blockSize = 5

img_channels = 2
num_disp = 16 * 8

param = {
    'preFilterCap': 63,     #映射滤波器大小,默认15
    "minDisparity" : 0,    #最小视差
    "numDisparities" : num_disp,    #视差的搜索范围,16的整数倍
    "blockSize" : blockSize,
    "uniquenessRatio" : 10,     #唯一检测性参数,匹配区分度不够,则误匹配(5-15)
    "speckleWindowSize" : 0,      #视差连通区域像素点个数的大小(噪声点)(50-200)或用0禁用斑点过滤
    "speckleRange" : 1,             #认为不连通(1-2)
    "disp12MaxDiff" : 2,        #左右一致性检测中最大容许误差值
    "P1" : 8 * img_channels * blockSize** 2,   #值越大,视差越平滑,相邻像素视差+/-1的惩罚系数
    "P2" : 32 * img_channels * blockSize** 2,  #同上,相邻像素视差变化值>1的惩罚系数
    # 'mode': cv2.STEREO_SGBM_MODE_SGBM_3WAY
    }
## 开始计算深度图
left_matcher = cv2.StereoSGBM_create(**param)
left_disp = left_matcher.compute(imgL_gray, imgR_gray)
# 得到深度图
disp = cv2.normalize(dispL, dispL, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

效果
【双目视觉】双目立体匹配

二、wls滤波

从上面的结果来看,深度图存在很多“黑色区域”,“黑色区域”是没有正确匹配的地方,也就是说这部分是没有深度信息的,这种情况就是“不够稠密”。
在opencv的扩展包opencv-contrib里提供了一种WLS视差滤波的办法,可以使得重建更加稠密。
改进部分为立体匹配部分,在经过立体匹配后再做一步处理:

## 接上面的参数
left_matcher = cv2.StereoSGBM_create(**param)

right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)

left_disp = left_matcher.compute(imgL_gray, imgR_gray)
right_disp = right_matcher.compute(imgR_gray, imgL_gray)
wls_filter = cv2.ximgproc.createDisparityWLSFilter(left_matcher)
# sigmaColor典型范围值为0.8-2.0
wls_filter.setLambda(8000.)
wls_filter.setSigmaColor(1.3)
wls_filter.setLRCthresh(24)
wls_filter.setDepthDiscontinuityRadius(3)

filtered_disp = wls_filter.filter(left_disp, imgL_gray, disparity_map_right=right_disp)

disp = cv2.normalize(filtered_disp, filtered_disp, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

【双目视觉】双目立体匹配
可以看到滤波之后的深度图变得相当稠密了。
但这种办法有利有弊:好处就是重建变得稠密,弊端就是这种办法会抹除掉一些细节深度,使得一块地方由原来的不同深度变成同一高度。
举个例子,上图中的杯子在实际观察中他应该是圆柱形,但滤波之后整个杯身将变成同一高度,即原来的高度差被抹除了。因此该方法请根据具体情况决定是否使用。

三、open3d点云重建

open3d提供了RGBD重建的办法,具体实现如下:
首先要准备一个相机内参文件(这样做比较省事),命名为camera_intrinsic.json
根据左目相机内参矩阵:

fx 0 cx
0 fy cy
0 0 1

以列为顺序写入:

{
    "width": 960,
    "height": 960,
    "intrinsic_matrix": [
        fx,
        0,
        0,
        0,
        fy,
        0,
        cx,
        cy,
        1
    ]
}

保存,作为相机内参文件。再在主程序中继续接入以下代码:

# 获取内参
intrinsic = o3d.io.read_pinhole_camera_intrinsic("camera_intrinsic.json")
# 转换图像
color_image = o3d.geometry.Image(left_remap)
depth_image = o3d.geometry.Image(disp)
rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth(color_image, depth_image, depth_trunc=4.0, convert_rgb_to_intensity=False)
# 根据RGBD图像重建
temp = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd_image, intrinsic)
pcd.points = temp.points
pcd.colors = temp.colors
# 显示效果
o3d.visualization.draw_geometries_with_editing([pcd], window_name="3D", width=1280, height=720)

【双目视觉】双目立体匹配

四、OpenCV的点云重建

除此之外也可以用opencv自带的办法重建,这个重建速度要比open3d快很多。
处理时需要剪掉一些不合理的点云数据。

# 将h×w×3数组转换为N×3的数组
def hw3ToN3(points):
    height, width = points.shape[0:2]

    points_1 = points[:, :, 0].reshape(height * width, 1)
    points_2 = points[:, :, 1].reshape(height * width, 1)
    points_3 = points[:, :, 2].reshape(height * width, 1)

    points_ = np.hstack((points_1, points_2, points_3))

    return points_

def DepthColor2Cloud(points_3d, colors):
    rows, cols = points_3d.shape[0:2]
    size = rows * cols

    points_ = hw3ToN3(points_3d).astype(np.int16)
    colors_ = hw3ToN3(colors).astype(np.int64)

    # 颜色信息
    blue = colors_[:, 0].reshape(size, 1)
    green = colors_[:, 1].reshape(size, 1)
    red = colors_[:, 2].reshape(size, 1)
    # rgb = np.left_shift(blue, 0) + np.left_shift(green, 8) + np.left_shift(red, 16)
    rgb = blue + green + red

    # 将坐标+颜色叠加为点云数组
    pointcloud = np.hstack((points_, red/255., green/255., blue/255.)).astype(np.float64)

    # 删掉一些不合适的点
    X = pointcloud[:, 0]
    Y = pointcloud[:, 1]
    Z = pointcloud[:, 2]

    remove_idx1 = np.where(Z <= 0)
    remove_idx2 = np.where(Z > 1000)
    remove_idx3 = np.where(X > 1000)
    remove_idx4 = np.where(X < -1000)
    remove_idx5 = np.where(Y > 1000)
    remove_idx6 = np.where(Y < -1000)
    remove_idx = np.hstack((remove_idx1[0], remove_idx2[0], remove_idx3[0], remove_idx4[0], remove_idx5[0], remove_idx6[0]))

    pointcloud_1 = np.delete(pointcloud, remove_idx, 0)


    return pointcloud_1

上面的函数可以单独用一个脚本文件保存再导入。
主脚本文件加入以下代码:

threeD = cv2.reprojectImageTo3D(disp, camera_config.Q)
pointcloud = DepthColor2Cloud(threeD, left_remap)

# 转换为open3d的点云数据
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(pointcloud[:,:3])
pcd.colors = o3d.utility.Vector3dVector(pointcloud[:,3:])
o3d.visualization.draw_geometries_with_editing([pcd], window_name="3D", width=1280, height=720)

【双目视觉】双目立体匹配文章来源地址https://www.toymoban.com/news/detail-438891.html

到了这里,关于【双目视觉】双目立体匹配的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 双目立体标定与极线校正【双目立体视觉几何】

       在这篇博文中,我们来了解一下立体标定的过程。双目相机各自经过相机标定后,该如何把两个相机统一起来,获得物体三维信息呢?    那么在双目立体视觉中,通过把左右相机平面旋转到一个平面内,且行对齐,旋转后的左右相机平面具有相同的焦距f,且具有相同

    2024年02月10日
    浏览(39)
  • 从双目标定到立体匹配:pyton实践指南

    立体匹配是计算机视觉中的一个重要领域,旨在将从不同角度拍摄的图像匹配起来,以创建类似人类视觉的3D效果。实现立体匹配的过程需要涉及许多步骤,包括双目标定、立体校正、视差计算等。在这篇文章中,将介绍如何使用Python实现立体匹配的基本步骤和技巧。 下面的

    2024年02月11日
    浏览(30)
  • 使用opencv做双目测距(相机标定+立体匹配+测距)

    最近在做双目测距,觉得有必要记录点东西,所以我的第一篇博客就这么诞生啦~ 双目测距属于立体视觉这一块,我觉得应该有很多人踩过这个坑了,但网上的资料依旧是云里雾里的,要么是理论讲一大堆,最后发现还不知道怎么做,要么就是直接代码一贴,让你懵逼。 所以

    2024年01月20日
    浏览(26)
  • 双目立体视觉空间坐标精度分析

    参考链接:https://zhuanlan.zhihu.com/p/362718946 本文主要参考链接博主的理论推导,并按照自己的理解作分析和修正 双目立体视觉系统的精度由那些因素决定? X/Y/Z三个方向的精度都是一样的吗?如果不是一样,哪个方向精度更好呢? 最常见的情况下,双目立体视觉的最终输出是

    2024年02月10日
    浏览(27)
  • 计算机视觉之三维重建(5)---双目立体视觉

     如下图即是一个平行视图。特点:(1) 两个平面平行。 (2) 基线平行于图像平面,极点 e e e 和 e ′ e\\\' e ′ 位于无穷远处。  1. 对于基础矩阵我们有另一个表达式: F = e ′ × K ′ R K − 1 F=e\\\'×K\\\'RK^{−1} F = e ′ × K ′ R K − 1 ,推导过程如下所示。  2. 在平行视图情况下,极点

    2024年04月12日
    浏览(38)
  • 双目立体视觉(一) 基本原理和步骤

    目录 一、双目立体视觉系统的四个基本步骤 二、各步骤原理 1、相机标定 2、立体校正 3、立体匹配 相机标定 主要包含两部分内容: 单相机的内参标定和双目相机的外参标定,前者可以获得每个相机的焦距、光心、畸变系数等参数,后者可以获得双目相机之间的相机坐标系的

    2024年02月14日
    浏览(32)
  • ZYNQ ARM+FPGA双目立体视觉控制器设计与实现(一)

    通过 ZYNQ 板卡实现 FPGA+ARM 架构的双目立体视觉系统 本设计采用实验室自主开发的 Zynq-7020 板卡,提出了基于 FPGA+ARM 架构的双 目立体视觉的软硬件系统设计方案。根据对系统软硬件功能划分, PL(FPGA) 端主要实现 了双目摄像头图像的采集存储和 HDMI 显示, PS(ARM) 端主要实现了

    2024年02月10日
    浏览(43)
  • 使用python-opencv对双目摄像头进行立体视觉图像矫正,去畸变

            1、一张棋盘图         可以直接从opencv官方github下载,这是一个拥有10*7个格子的棋盘,共有 9*6个角点,每个格子24mm ,本文所使用的就是这一个棋盘。你需要将它打印在A4纸上用于后续使用。(也可以根据官方教程自行设置棋盘大小OpenCV: Create calibration pattern)

    2024年02月10日
    浏览(37)
  • 双目立体匹配中的极线约束(Epipolar Constraint),基础矩阵(Fundamental Matrix),本质矩阵(Essential Matrix),对极几何(2D-2D)

    考虑一个SLAM中一个常见的问题:如果两个相机在不同位置拍摄同一个物体,或者一个运动的相机在不同时刻拍摄同一物体,我们有理由相信两张图片中各点存在着某种几何关系,这种关系可以用对极几何来描述。对极几何描述了两帧图像中各像素的射影关系(或者说是各匹配

    2024年02月05日
    浏览(26)
  • 基于MVS的三维重建算法学习笔记(三)— 立体匹配概述

    本人书写本系列博客目的是为了记录我学习三维重建领域相关知识的过程和心得,不涉及任何商业意图,欢迎互相交流,批评指正。 在之前的博客中简单介绍过立体匹配,它是MVS稠密重建中的重要环节,而在这篇博客中,将详细的介绍立体匹配的相关概念,其中详细的过程和

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包