Advertisement

【计算机视觉07】视差计算图

阅读量:

立体视觉

  • 一. 概念理解

    • 1.视差:
    • 2.窗口计算视差:
    • 3.影响视差的因素
  • 二. 视差计算步骤

  • 三. NCC视差匹配

  • 四. 代码

  • 五. 结果分析

一. 概念理解

1.视差:

在左右双目成像系统中,在左眼和右眼所成的图像中(即左右双目图像),对应区域中心点之间的横向间距被定义为视差值(disparity)。当该值越大时,则说明观察物体离摄像头越近(即物体与摄像头之间的距离与之相关联)。反之,在视差点的位置上(即离摄像头较远的地方),对应的视差点之间的横向间距会较小。

2.窗口计算视差:

创建一个较小的窗口,并以此为基础在左图上进行覆盖操作;提取该区域内所有像素点;同时,在右图中进行相同操作;计算左图中被选区与右图中被选区之间的差异;然后计算所有被选 pixels 的灰度差绝对值总和;此算法常用于图像块匹配问题中;该算法通过计算各 pixels 对应数值之差绝对值总和来评估两个图像块之间的相似程度。

3.影响视差的因素

1) 光学畸变与干扰(明度、色调、饱和度失衡)
2) 镜面反射特性
3) 投影尺寸缩减
4) 透视变形
5) 低纹理细节
6) 周期性纹理重复
7) 半透光物体
8) 复合结构与不连续性

二. 视差计算步骤

必须对相机进行标定

  1. 立体标定
    获取左右相机的空间转换关系

极线校正
在同一个空间中的一个点,在两张不同的图像中对应的映射关系经过极线校正后,在两张图像中对应点的y坐标保持一致,并且这种校正是为了减少需要进行匹配的点对数量

  1. 立体匹配
    通过计算各点之间的视差值,并对每个视差值进行计算后,则确定了各点的空间坐标。

三. NCC视差匹配

对于原始图像中的任意一个像素点(Px, Py), 我们需要建立一个n \times n的邻域区域作为匹配窗口. 同时, 我们还需要建立另一个n \times n大小的匹配窗口, 用于定位目标像素点(Px + d, Py). 通过计算两者之间的相似度, 我们能够确定d的具体取值范围. 在实际应用中, 进行NCC(归一化相关性交叉)计算之前, 需要对图像进行预处理工作. 这种预处理包括将两幅图像水平对齐, 并确保光心处于同一水平位置. 这种操作使得极线呈现水平状态. 如果极线并非水平分布, 那么在倾斜方向上完成匹配过程将会消耗更多的计算资源.

在这里插入图片描述

四. 代码

复制代码
    /# -*- coding: utf-8 -*-
    from PIL import Image
    from pylab import *
    import cv2
    from numpy import *
    from numpy.ma import array
    from scipy.ndimage import filters
    def plane_sweep_ncc(im_l,im_r,start,steps,wid):
    """ 使用归一化的互相关计算视差图像 """
    m,n = im_l.shape
    # 保存不同求和值的数组
    mean_l = zeros((m,n))
    mean_r = zeros((m,n))
    s = zeros((m,n))
    s_l = zeros((m,n))
    s_r = zeros((m,n))
    # 保存深度平面的数组
    dmaps = zeros((m,n,steps))
    # 计算图像块的平均值
    filters.uniform_filter(im_l,wid,mean_l)
    filters.uniform_filter(im_r,wid,mean_r)
    # 归一化图像
    norm_l = im_l - mean_l
    norm_r = im_r - mean_r
    # 尝试不同的视差
    for displ in range(steps):
        # 将左边图像移动到右边,计算加和
        filters.uniform_filter(np.roll(norm_l, -displ - start) * norm_r, wid, s) # 和归一化
        filters.uniform_filter(np.roll(norm_l, -displ - start) * np.roll(norm_l, -displ - start), wid, s_l)
        filters.uniform_filter(norm_r*norm_r,wid,s_r) # 和反归一化
        # 保存 ncc 的分数
        dmaps[:,:,displ] = s / sqrt(s_l * s_r)
        # 为每个像素选取最佳深度
    return np.argmax(dmaps, axis=2)
    
    def plane_sweep_gauss(im_l,im_r,start,steps,wid):
     """ 使用带有高斯加权周边的归一化互相关计算视差图像 """
     m,n = im_l.shape
     # 保存不同加和的数组
     mean_l = zeros((m,n))
     mean_r = zeros((m,n))
     s = zeros((m,n))
     s_l = zeros((m,n))
     s_r = zeros((m,n))
     # 保存深度平面的数组
     dmaps = zeros((m,n,steps))
     # 计算平均值
     filters.gaussian_filter(im_l,wid,0,mean_l)
     filters.gaussian_filter(im_r,wid,0,mean_r)
     # 归一化图像
     norm_l = im_l - mean_l
     norm_r = im_r - mean_r
     # 尝试不同的视差
     for displ in range(steps):
     # 将左边图像移动到右边,计算加和
     filters.gaussian_filter(np.roll(norm_l, -displ - start) * norm_r, wid, 0, s) # 和归一化
     filters.gaussian_filter(np.roll(norm_l, -displ - start) * np.roll(norm_l, -displ - start), wid, 0, s_l)
     filters.gaussian_filter(norm_r*norm_r,wid,0,s_r) # 和反归一化
     # 保存 ncc 的分数
     dmaps[:,:,displ] = s / np.sqrt(s_l * s_r)
     # 为每个像素选取最佳深度
     return np.argmax(dmaps, axis=2)
    
    im_l = array(Image.open(r'D:\PycharmProjects\photo\left.png').convert('L'), 'f')
    im_r = array(Image.open(r'D:\PycharmProjects\photo\right.png').convert('L'),'f')
    # 开始偏移,并设置步长
    steps = 12
    start = 4
    # ncc 的宽度
    wid = 10
    res = plane_sweep_ncc(im_l,im_r,start,steps,wid)
    import scipy.misc
    scipy.misc.imsave('depth1.png',res)
    show()

五. 结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  • 被圈出的区域因物体表面反射较强的原因,在实际应用中难以准确判断其与摄像头之间的远近距离。
  • 窗口大小直接影响最终结果的表现:较大的模板会产生较低水平的深度图噪声;计算开销增加且过大的模板会导致物体边缘细节信息丢失。

全部评论 (0)

还没有任何评论哟~