完整源码链接 https://github.com/LamyaLi/cvLab

一、 立体匹配的研究背景及意义

立体视觉是计算机视觉领域的一个重要课题,它的目的在于重构场景的三维几何信息。立体视觉的研究具有重要的应用价值,其应用包括移动机器人的自主导航系统,航空及遥感测量,工业自动化系统等。 

立体视觉的研究方法之一,利用多幅图象来恢复三维信息的方法,它是被动方式的。根据图象获取方式的区别又可以划分成普通立体视觉和通常所称的光流(optical flow)两大类。普通立体视觉研究的是由两摄像机同时拍摄下的两幅图象,而光流法中研究的是单个摄像机沿任一轨道运动时顺序拍下的两幅或更多幅图象。前者可以看作后者的一个特例,它们具有相同的几何构形,研究方法具有共同点。双目立体视觉是它的一个特例。 

在这里插入图片描述

其中立体匹配是立体视觉系统的核心,是建立图像间的对应从而计算视差的过程,是极为重要的。立体匹配有两类算法: 

(1) 基于灰度的算法 (intensity based),
(2) 基于特征的算法 (feature based)。

二、 立体匹配算法的基本实现思想

​ 本文使用的立体匹配算法思想来源于《Obtaining Depth Maps From Color Images By Region Based Stereo Matching Algorithms》。该算法属于基于灰度的匹配算法,这是一种区域相关方法, 在一幅图象中以一点为中心选定一区域(窗口),在另一幅图象中寻找与该区域相关系数最大的区域,把该找到的区域的中心认为是原来那区域中心的对应点。它对噪声很敏感,所以需要搭配去噪滤波使用。

1、误差能量函数

选取匹配计算区域窗口大小是(m*n)

d是视差,我们需要先定一个视差搜寻范围如dmax=40

在这里插入图片描述

由于该算法对噪声敏感,进一步计算平均error energy
在这里插入图片描述

2、基于最小平均误差能量的视差图

选取error energy最小的d作为视差图中(i,j)点的d,得到视差图

在这里插入图片描述

3、计算可靠度,生成具有可靠视差的视差图

前两步得到的视差图是有噪声的,可以先用中值滤波处理一遍。

定一个阈值ve,将error energy低于它的筛掉:在这里插入图片描述alpha是系数,系数越低,可靠度越高,但是去噪效果越不好。

在这里插入图片描述
在这里插入图片描述

其中sd是,不是ne的数量

4、由视差图生成深度图

根据这个三角关系,由视差图计算深度图,
在这里插入图片描述
在这里插入图片描述

三、 实现步骤与结果展示

在这里插入图片描述左相机图
在这里插入图片描述右相机图

1、计算误差能量,生成具有最小平均误差能量的视差图
for d in range(dmax):
    ##先计算  e (i,j,d)
    for i in range(size1):
        for j in range(size2):
            sum =0
            for m in range(window_size):
                for n in range(window_size):
                    for k in range(3):
                        x=min(size1-1,i+m)
                        y=min(size2-1,j+n)
                        square_diff=(int(left[x][min(y+d,size2-1)][k])-int(right[x][y][k]))**2
                        sum=sum+square_diff
            e[i][j]=sum/(3*window_size*window_size)

    ##再计算e_avg(i,j,d)
    for i in range(size1):
        for j in range(size2):
            e_temp = 0
            for m in range(window_size):
                for n in range(window_size):
                    x = min(size1-1, i + m)
                    y = min(size2-1, j + n)
                    e_temp=e_temp+e[x][y]
            e_temp=e_temp/(window_size*window_size)
            if e_temp<e_avg[i,j]:
                e_avg[i,j]=e_temp
                disparity[i,j]=d

对视差图增强对比度显示(右边是增强对比度的):

#######增强对比度显示
temp=cv2.imread('disparity_base.png')
gray = cv2.cvtColor(temp, cv2.COLOR_RGB2GRAY) #opencv的直方图均衡化要基于单通道灰度图像
dst = cv2.equalizeHist(gray)
cv2.imwrite('disparity_base_enhanced.png', dst)
temp2=cv2.imread('disparity_base_enhanced.png')
cv2.imshow('视差图(原图->对比度增强显示)', np.hstack([temp,temp2]))
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

2、计算可靠度,生成可靠视差的视差图

可以看到上面的结果图,噪声点很多,很多视差是不可靠的,所以这一步很必要。

########################################用中值滤波处理视差图
cv2.medianBlur(disparity,3)
##########################################计算具有可靠视差的视差图
ve=alpha*e_avg.mean()
count_not_ne=0
sum_e=0
for i in range(size1):
    for j in range(size2):
        if e_avg[i][j]>ve:
                ######定ne
            disparity[i][j]=0
        else:
            sum_e=sum_e+e_avg[i][j]
            count_not_ne=count_not_ne+1
reliability=float(count_not_ne)**(-1)*sum_e
print("!!!!!!!!可靠度:",reliability)

在这里插入图片描述
在这里插入图片描述

3、计算深度图

其中将视差小于5的视为噪声处理

epth=np.ones_like(disparity,dtype=np.uint8)
for i in range(size1):
    for j in range(size2):
        if disparity[i][j]<5: ##噪音
            depth[i][j]=0
        else:
            depth[i][j]=f*T//disparity[i][j]

cv2.medianBlur(depth,3)

在这里插入图片描述

4、3D显示深度图
X=range(size1)
Y=range(size2)
Z=depth
xx, yy=np.meshgrid(X, Y)#网格化坐标
X, Y=xx.ravel(), yy.ravel()#矩阵扁平化
bottom=np.zeros_like(X)#设置柱状图的底端位值
Z=Z.ravel()#扁平化矩阵

width=height=1#每一个柱子的长和宽

fig=plt.figure()
ax=fig.gca(projection='3d')#三维坐标轴
ax.bar3d(X, Y, bottom, width, height, Z, shade=True)#
#坐标轴设置
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z(depth)')
plt.show()

.gca(projection=‘3d’)#三维坐标轴
ax.bar3d(X, Y, bottom, width, height, Z, shade=True)#
#坐标轴设置
ax.set_xlabel(‘X’)
ax.set_ylabel(‘Y’)
ax.set_zlabel(‘Z(depth)’)
plt.show()
``
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐