双目匹配代码分析
原理
通过将两个水平放置的摄像头获取的图像,匹配相应的区域视差。方式有很多种,SAD是速度最快的方式,主要原理是块匹配,计算每个搜索块在最大视差范围内的sad值,选择最小的sad值的水平位移距离作为视差输出。
一、区准函数
主要的算法只有一个函数,这里输出的是两幅图像在x方向上的sobel变化后的图像。并且通过查找表归一化数据,可以去掉一些亮度影响。
static void findStereoCorrespondence( const Mat& left, const Mat& right,
Mat& disp, Mat& cost, const CvStereoBMState& state,
uchar* buf, int _dy0, int _dy1 )
- 创建查找表tab
for( x = 0; x < TABSZ; x++ )
tab[x] = (uchar)std::abs(x - ftzero);
得到tab(0:255) = (31:0, 1:224)
- 初始化第一列的搜索窗
for( x = -wsz2-1; x < wsz2; x++ )
{
hsad = hsad0 - dy0*ndisp;
cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp;
// 最大视差比搜索窗大很多的情况下,不需要判断边界
lptr = lptr0 + x - dy0*sstep;//std::min(std::max(x, -lofs), width-lofs-1) - dy0*sstep;//
rptr = rptr0 + x - dy0*sstep;//std::min(std::max(x, -rofs), width-rofs-1) - dy0*sstep;//
//int val;
for( y = -dy0; y < height + dy1; y++,
hsad += ndisp, cbuf += ndisp,
lptr += sstep, rptr += sstep )
{
// 左边减去右边差的绝对值,在最大视差范围内计算
int lval = lptr[0];
for( d = 0; d < ndisp; d++ )
{
int diff = std::abs(lval - rptr[d]);
//cbuf[dy0+height+dy1][ndisp]
cbuf[d] = (uchar)diff; // 每一列,当前像素与对应像素差值
hsad[d] = (int)(hsad[d] + diff);//搜索窗里sad
}
htext[y] += tab[lval]; // 计算一个搜索窗里左图像素-31的绝对值之和
//val = lval;
}
}
计算左图与右图残差值,每个像素都减去右图水平偏移0~disp-1个像素
for x = -wsz2-1:wsz2
cbuf(x, -dy0:height+dy1, 0:disp-1) = abs(tab(Left(x, -dy0:height+dy1))-tab(right(x:x+disp, -dy0:height+dy1)))
end
先cbuf初始一个搜索窗的残差值,一共(ws