最近开始研究双目匹配算法,于是在网上代码网站比如CSDN,GITHUB,虽然找到很多代码,但是由于用的编译环境或者库不一样,导致有些代码无法理解,所以,为了得到自己想要的结果,本人花了几天的时间根据算法的基本原理,结合自己的编译环境,编写了代码。具体代码和步骤如下所示:
编译环境: visual studio 2015 + opencv3.2.0
先对SAD立体匹配算法做一个详细的解释(摘抄自某个作者的博客)。
SAD 算法:SAD算法是一种最简单的匹配算法,用公式表示为:
SAD(x,y,d) = Sum{|Left(x,y) - Right(x,y,d)|} 选择最小值,其中d为视差范围
此方法就是以左目图像的匹配点为中心,定义一个窗口D,其大小为 (2 * hwind+1) (2 * hwind+1),统计其窗口的灰度值的和,然后在右目图像中逐步计算其左右窗口的灰度和的差值,最后搜索到的差值最小的区域的中心像素即为匹配点。
基本流程:
1.构造一个小窗口,类似与卷积核。
2.用窗口覆盖左边的图像,选择出窗口覆盖区域内的所有像素点。
3.同样用窗口覆盖右边的图像并选择出覆盖区域的像素点。
4.左边覆盖区域减去右边覆盖区域,并求出所有像素点差的绝对值的和。
5.移动右边图像的窗口,重复3,4的动作。(这里有个搜索范围,超过这个范围跳出)
6.找到这个范围内SAD值最小的窗口,即找到了左边图像的最佳匹配的像素块。
以下这段话是对于双目立体匹配小白而言的,如果读者对于双目匹配有一定的了解,可以直接略过这段话直接看下面的程序。
有些人看到上面的这段定义就疑惑了,想着为什么两幅图像相减就能得到立体的图像呢。下面为大家解释一下。
大家看到上面的这两幅图像,renwu_left(以下统称为左图),renwu_right(以下统称为右图)。在这两个图像的最右边我标记了两个红色的方框。从图中可以看出,左图相对于右图相对靠左,所以说,在左图中要找到与右图相匹配的像素,就要在固定左图Left(x,y)的前提下,在右图中以同样的坐标为基点 Right(x,y),向左寻找匹配区域 Right(x,y,d)//d为选择移动的像素范围。 这样通过遍历图像,就可以得到匹配图像。又有读者问了,就算匹配上,那怎么得到深度呢?下面为读者解释一下(这个概念也是花了我好长时间才搞明白的)