计算视差图

  • 1. 立体视差
  • 2. 极线矫正
  • 3. 归一化互相关(NCC)
  • 4 . 计算视差图的步骤
  • 5. 实验过程
    • 5.1 实验代码
    • 5.2 实验结果及分析
      • 5.2.1 视差图计算结果
      • 5.2.2 不同窗口值(wid)的视差图
  • 6. 实验中遇到的问题及解决

1. 立体视差

立体视差 ,亦称立体视像、立体知觉。基于双眼视差所 获得的深度知觉。

立体视差的测量包括三个步骤:
(1)必须从一幅图像中选出位于场景中一个表面上的某一特定位置;
(2)必须在另一幅图像中鉴别出同一个位置;
(3)测出这两个对应像点之间的视差。

在一组重复摄影的两张照片上(立体模式),同一地物的影象,沿着摄影基线(摄影地点和下一个摄影地点之间的飞行方向线)方向位置变换,这个变化量叫“立体视差”。

立体视差在每张照片上,从那点到照片基线(临接摄影地点与照片的摄影地点的像连结的直线),下垂线的足和主点(相片中心)之间叫距离之和。这是把相对两个照片的基线方向,使其成为一直线,按摄影顺序排列时,和相应的同一地物影象间的两个照片主点之间的间隔差。

2. 极线矫正

一个多视图成像的特殊例子是立体视觉(或者立体成像),即使用两台只有水平(向一侧)偏移的照相机观测同一场景。当照相机的位置只有水平偏移观测同一场景时,两幅图像具有相同的图像平面,图像的行是垂直对齐的,那么称图像对是经过矫正的。该设置在机器人学中很常见,常被称为立体平台

极线矫正:通过将图像扭曲到公共的平面上,使外极线位于图像行上,任何立体照相机设置都能得到矫正(我们通常构建立体平台来产生经过矫正的图像对)。

假设两幅图像经过了矫正,那么对应点的寻找限制在图像的同一行上。一旦找到对应点,由于深度是和偏移成正比的,那么深度(Z 坐标)可以直接由水平偏移来计算,如下图所示:

其中, f f f 是经过矫正图像的焦距, T T T是两个照相机中心之间的距离, x l x_l xl​ 和 x r x_r xr​ 是左右两幅图像中对应点的 x x x坐标。分开照相机中心的距离称为基线。

根据上图可以得到相似三角形:
Δ ( p l , p , p r ) ∼ Δ ( O l , p , O r ) \Delta (p_l,p,p_r)\sim \Delta (O_l,p,O_r) Δ(pl​,p,pr​)∼Δ(Ol​,p,Or​)
根据相似三角形的性质可以得出如下公式:
T + x l − x r T = Z − f Z \frac{T+x_l-x_r}{T} = \frac{Z-f}{Z} TT+xl​−xr​​=ZZ−f​
所以深度(Z 坐标)的计算如下:
Z = f T x r − x l Z=f\frac{T}{x_r-x_l} Z=fxr​−xl​T​

立体重建(有时称为致密深度重建)就是恢复深度图(或者相反,视差图),图像中每个像素的深度(或者视差)都需要计算出来。

3. 归一化互相关(NCC)

在立体重建算法中,我们将对于每个像素尝试不同的偏移,并按照局部图像周围归一化的互相关值,选择具有最好分数的偏移,然后记录下该最佳偏移。因为每个偏移在某种程度上对应于一个平面,所以该过程有时称为扫平面法。

归一化互相关(NCC)算法的原理如下:如有校正过的两帧图像 I 1 I_1 I1​,、 I 2 I_2 I2​,NCC算法对图像 I 1 I_1 I1​一个待匹配像素构建n*n匹配窗口,在图像 I 2 I_2 I2​极线上对每一个像素构建匹配窗口与待匹配像素匹配窗口计算相关性,相关性最高的视为最优匹配。由于NCC匹配流程是通过在同一行中查找最优匹配,因此它可以并行处理,对于运行效率有一定的提升。

我们使用每个像素周围的图像块(根本上说,是局部周边图像)来计算归一化的互相关。针对图像,像素周围重新写出公式中的NCC,如下所示:
n c c ( I 1 , I 2 ) = ∑ x ( I 1 ( x ) − u 1 ) ( I 2 ( x ) − u 2 ) ( ∑ x ( I 1 ( x ) − u 1 ) 2 ∑ x ( I 2 ( x ) − u 2 ) 2 ) ncc(I_1,I_2)=\frac{\sum_{x}(I_1(x)-u_1)(I_2(x)-u_2)}{\sqrt(\sum_{x}(I_1(x)-u_1)^2\sum_{x}(I_2(x)-u_2)^2)} ncc(I1​,I2​)=( ​∑x​(I1​(x)−u1​)2∑x​(I2​(x)−u2​)2)∑x​(I1​(x)−u1​)(I2​(x)−u2​)​

4 . 计算视差图的步骤

经过上述分析,可以得到计算视差图的基本步骤如下:

  1. 极线校正:校正的目的是使两帧图像极线处于水平方向,或者说是使两帧图像的光心处于同一水平线上。通过校正极线可以方便后续的NCC操作。
  2. 特征匹配:这里便利用NCC做匹配的步骤,匹配方法如上所述,右视图中与左视图待测像素同一水平线上相关性最高的即为最优匹配。完成匹配后,我们需要记录其视差 d d d,即待测像素水平方向 x l x_l xl​与匹配像素水平方向 x r x_r xr​之间的差值 x r − x l x_r - x_l xr​−xl​,由极线矫正部分中推导出的公式 Z = f T x r − x l Z=f\frac{T}{x_r-x_l} Z=fxr​−xl​T​, f 、 T f、T f、T已知,即可算出深度Z。最终我们可以得到一个与原始图像尺寸相同的视差图D。
  3. 深度恢复:通过上述匹配结果得到的视差图D,可以很简单的利用相似三角形反推出以左视图为参考系的深度图。

5. 实验过程

在本次实验中,首先实现视差图的计算,其次改变窗口值(wid)观察实验结果并分析窗口值(wid)对视差图的影响。

5.1 实验代码

from PIL import Image
from pylab import *
import numpy as np
import scipy.ndimage.filters as filters
import scipy.misc# 使用归一化的互相关计算视差图像
def plane_sweep_ncc(im_l,im_r,start,steps,wid):m, n = im_l.shape# 保存不同求和值的数组mean_l = np.zeros((m, n))mean_r = np.zeros((m, n))s = np.zeros((m, n))s_l = np.zeros((m, n))s_r = np.zeros((m, n))# 保存深度平面的数组dmaps = np.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_lnorm_r = im_r - mean_r# 尝试不同的视差for displ in range(steps):#将左边图像移动到右边,计算加和filters.uniform_filter(roll(norm_l, -displ - start) * norm_r, wid, s)  # 和归一化filters.uniform_filter(roll(norm_l, -displ - start) * roll(norm_l, -displ - start), wid, s_l)filters.uniform_filter(norm_r * norm_r, wid, s_r)  # 和反归一化# 保存ncc 的分数dmaps[:, :, displ] = s / np.sqrt((s_l * s_r)+1e-5)# 为每个像素选取最佳深度return 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_lnorm_r = im_r - mean_r# 尝试不同的视差for displ in range(steps):# 将左边图像移动到右边,计算加和filters.gaussian_filter(roll(norm_l,-displ-start)*norm_r,wid,0,s) # 和归一化filters.gaussian_filter(roll(norm_l,-displ-start)*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 argmax(dmaps,axis=2)if __name__ == '__main__':im_l = array(Image.open('data/3.jpg').convert('L'), 'f')im_r = array(Image.open('data/4.jpg').convert('L'), 'f')# 开始偏移,并设置步长steps = 12start = 4# ncc 的宽度wid = 9res1 = plane_sweep_ncc(im_l, im_r, start, steps, wid)scipy.misc.imsave('depth1.png', res1)# scipy.misc.imsave('depth2wid'+str(wid)+'.png', res1)res2 = plane_sweep_gauss(im_l, im_r, start, steps, wid)scipy.misc.imsave('depth2.png', res2)

5.2 实验结果及分析

5.2.1 视差图计算结果

① 第一组图像的NCC均匀滤波器视差图和NCC高斯滤波器视差图结果
NCC均匀滤波器视差图:wid=9
NCC高斯滤波器视差图:wid=3

② 第一组图像的NCC均匀滤波器视差图和NCC高斯滤波器视差图结果
NCC均匀滤波器视差图:wid=27
NCC高斯滤波器视差图:wid=9

以上实验结果是两组图像分别实现均匀滤波器计算视差和高斯滤波器计算视差的方法,可以看出:
与均值滤波版本相比,高斯滤波版本具有较少的噪声,但缺少很多细节信息。 对于第一组图像来说均匀滤波器计算出的视差图较为容易观察一些,而对于第二组图像来说其均匀滤波器计算出的视差图太过杂乱,使用高斯滤波器计算的视差图较为平滑,减少了均匀滤波器的杂乱感更容易观察一些。
分析原因如下:
均匀滤波器给定正方形图像块中所有像素相同的权值,所以可以观察到使用均匀滤波器得到的视差图没有那么平滑。而高斯滤波器高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到,所以而后使用高斯滤波器替换均匀滤波器,可以看到产生了更加平滑视差图。

均匀滤波器和高斯滤波器的区别:
其窗口模板的系数和均值滤波器不同,均值滤波器的模板系数都是相同的为1;而高斯滤波器的模板系数,则随着距离模板中心的增大而系数减小。所以,高斯滤波器相比于均值滤波器对图像个模糊程度较小。

对于接下来考虑wid值对于视差图计算的影响进行实验,所以选用较为容易观察的数据进行实验,即第一组图像中的NCC均匀滤波器的方法。

5.2.2 不同窗口值(wid)的视差图

观察代码可知:wid值在主函数中进行赋值,从而作为参数传给计算视差图的函数,在计算视差图的函数中再次将wid值作为参数传给均匀滤波器的方法。即wid值的影响应该为:先影响滤波结果,再接着滤波结果影响视差图的计算,所以在进行分析的时候应首先考虑wid值对滤波的影响,再考虑滤波对是视差图的影响。

随着wid值的改变,即改变了滤波器的模板大小,对于均值滤波器来说,经过滤波后图像的每一个像素的灰度值都是原图像中窗口值大小内的所有灰度值的均值,可以得到结论:当wid值越小,得到的像素值越不能参考周围像素点的灰度值;当wid值越大,得到的像素值越能参考周围像素点的灰度值。

实验结果分为两部分:第一部分为不同wid值整合在一起进行对比的图像,如下六张图分别是wid不同值的图像整合在一张图中,用来观察轮廓及大致影响。第二部分为六张不同wid值的细节图,用于观察细节。

在观察实验结果的时候需注意:灰度值越小的地方视差越小,即距离照相机越近。

(一) 第一部分

由上图观察可得:随着wid值的增大,图像深度信息的图像的轮廓逐渐明显,可以大致看出距离照相机最近的物体即为台灯,但较远处的物体就无法分辨。
可以得出结论:
wid值越大,产生的深度图噪声小,然而计算代价高。模板太大会丢失物体边缘上的细节。

进而思考:wid值影响了滤波结果,滤波结果影响了NCC的匹配度的计算。当wid值较小,滤波结果就较为局限,进而NCC的匹配度就会不准确,然后在计算视差的时候可能造成匹配到的不是同一特征点,最后计算出的视差会有误差,视差图就较为杂乱不易观察;在wid值较大的时候,滤波结果就较为开放,可以考虑到周围像素的影响,进而降低NCC匹配度的误差,得到的视差图轮廓明显,易观察。

(二) 第二部分

① wid=3

② wid=5

③ wid=7

④ wid=9

⑤ wid=11

⑥ wid=13

在这六幅图像中,选取台灯为观察点截取局部图像如下:

3/9 5/11 7/13

可以看到当wid值较小的时候台灯的两根支架的细节信息是很丰富的,虽然当wid=3时整张图像很杂乱,无法抓住重点,担当截取出台灯的部分可以看到其细节是很丰富的,随着wid值的增大台灯两根支架的细节信息逐渐消失。

由于wid值影响了滤波结果,滤波结果影响了NCC的匹配度的计算。可以分析:当wid值较小,滤波结果仅仅只受自身和周围较少像素的影响,所以就会保留更多自身的特征性在,进行NCC的匹配计算视差的时候细节信息就会更丰富一些,但也可以看到当wid值较小的时候视差图是很杂乱的,无法直接观察出视差的区别。;在wid值较大的时候,可以考虑到周围像素的影响,可以使自身和周围像素更好地融合,得到的视差图的轮廓信息较为明显,易观察。

总结以上所有分析过程可以得到如下实验结论:

  1. wid值越大,细节更丰富,但噪声点更多。
  2. wid值越小,稳健性更好,但细节信息更少。

6. 实验中遇到的问题及解决

1.在进行实验的过程中遇到如下报错:

RuntimeError: output shape not correct

经过排查发现同一组的两幅图像尺寸不一致如下:

使用python库中图像处理的函数更改图像尺寸大小即可。

2.在进行实验的过程中遇到如下警告:

RuntimeWarning: divide by zero encountered in true_dividedmaps[:, :, displ] = s / np.sqrt((s_l * s_r))

其原因大致时因为根号下的数不能为0,所以将改行代码更改为:

dmaps[:, :, displ] = s / np.sqrt((s_l * s_r)+1e-5)

为根号下的数字加上1e-5,其数值不大,对原本数据也不会造成影响,所以造成的影响不大,同时也解决了根号下不能为0的问题。

计算机视觉——计算视差图相关推荐

  1. python计算机视觉编程——立体图像之计算视差图

    计算视差图 一.立体图像 1.1概念 1.2关于图像配准算法 二.立体重建之计算视差图 2.1归一化及算法概念 2.2匹配流程 三.实验测试 3.1实验要求 3.2实验代码 3.3实验结果分析 3.4 ...

  2. 立体图像——NCC匹配方法计算视差图

    文章目录 一.什么是立体图像 二.以窗口代价计算视差的原理 三.归一化互相关(NCC)算法匹配原理 四.实验 1.实验要求 2.实验代码 3.实验结果 五.实验小结 一.什么是立体图像 一个多视图成像 ...

  3. 计算机视觉——计算视差

    一.实验原理 1.1 双目视差与深度距离关系推导详解 相机成像的模型如下图所示: P为空间中的点,P1和P2是点P在左右像平面上的成像点,f是焦距,OR和OT是左右相机的光心.由下图可见左右两个相机的 ...

  4. 归一化互相关(NCC)计算视差图

    文章目录 一.NCC 1.1 NCC原理 1.2 实现步骤 二.代码实现 2.1 相关代码 2.2 运行结果 2.2.1 修改窗口大小的影响 2.2.1.1 窗口大小win=3时 2.2.1.2 窗口 ...

  5. python 深度 视差 计算_NCC视差匹配计算视差图(python)

    目录 一.视差计算原理 1.1 NCC视差匹配方法 1.2 双目立体匹配 二.实验内容 2.1 不同窗口对匹配结果的影响 2.2 分析 三.实验代码 四.总结 一.视差计算原理 1.1 NCC视差匹配 ...

  6. 双目测距 视差图(不完善)

    博主INBC 删掉点云之后 效果 # -*- coding: utf-8 -*- import cv2 import numpy as np import stereoconfig_040_2 # 导 ...

  7. 双目立体视觉:四(双目标定matlab,图像校正,图像匹配,计算视差,disparity详解,)

    二郎也比较忙,在某大场工作,有时候没有时间回复. 如果希望二郎尽快帮忙,可以将代码,数据和问题发给二郎,谢谢大家理解. glwang20@mails.jlu.edu.cn 不过还是希望大家自己要好好研 ...

  8. 双目立体视觉建立深度图_计算机视觉实验五 双目立体匹配获得视差图,深度图...

    完整源码链接 https://github.com/LamyaLi/cvLab 文章目录 一. 立体匹配的研究背景及意义 二. 立体匹配算法的基本实现思想 1.误差能量函数 2.基于最小平均误差能量的 ...

  9. 双目立体视觉 II:块匹配视差图计算

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:Ali Yasin Eser 编译:ronghuaiyang(AI 公园) 导读 双目立体视觉的 ...

最新文章

  1. exchange2003如何恢复邮件
  2. pytorch randomresizedcrop
  3. 6.5 如何确定聚类数-机器学习笔记-斯坦福吴恩达教授
  4. 如何使用grup制作U盘多重启动盘
  5. list中存储map的情况下,遍历list
  6. js input 自动换行_矿用自动灭火装置水基型自动灭火装置原理国内分析研讨_搜狐汽车...
  7. LeetCode 题 - 20. 有效的括号
  8. Dom4j中getStringValue()和getText()用法的区别
  9. php 调用永中云,永中优云:是时候给大家介绍真正的云端Office了
  10. C#对dll文件的反编译
  11. python多叉树_python中高效的四叉树实现
  12. ESP8266 读取MPU-6050数据OLED显示
  13. 2019ICPC徐州 H - Yuuki and a problem (动态(带修)主席树 + 区间Mex问题)
  14. JavaScript计算圆周率(解析几何+定积分)
  15. 无线路由的四种加密方式
  16. 利用IDEA将项目打包(两种方法)
  17. 颜色值透明度的百分数对应十六进制表
  18. xxx牌JUC学习加油奥利给001初始篇章
  19. [Leetcode刷题心得][数组、字符串]242. 有效的字⺟母异位词
  20. easyui-combobox加载json中对象的属性

热门文章

  1. 青龙面板搭建教程安装,使用拉库持续更新,干什么用,我不说?
  2. dialog.show()不显示也不报错
  3. 单片机开发,常用的一些知识
  4. 他说:“程序员是出轨率最高群体”,然后就被解约了...
  5. springboot选择题、判断题
  6. 信息与通信工程学科面试准备——通信原理
  7. html 提示语为英文,耳熟能详的电话提示语英文版
  8. 【element-ui】
  9. (静态,动态,文件)三个版本的通讯录
  10. 写给自己,人生路远,勿忘初心