我正在尝试增强 stereobm(Opencv 立体 block 匹配)。 他们声称该算法使用 SAD cost_function 方法。 (ABOSLUE 差异的 SAD 总和)。
但是在代码中 他们以这种方式计算了 SAD:
for( y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp,
hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep )
{
int lval = lptr[0];
for( d = 0; d < ndisp; d++ )
{
int diff = std::abs(lval - rptr[d]);
cbuf[d] = (uchar)diff;
hsad[d] = hsad[d] + diff - cbuf_sub[d];
}
htext[y] += tab[lval] - tab[lptr_sub[0]];
}
......
sad[d] = (int)(hsad0[d-ndisp*dy0]*(wsz2 + 2 - dy0));
// *******************************
Instead of
//....
hsad[d] = hsad[d] + diff ;
// .....
sad[d] = hsad[d]
那么,为什么他们用 *(wsz2 + 2 - dy0)) 进行乘法运算?
以及为什么他们从 hsad[d] 中减去 cbuf_sub[d](hsad[d] = hsad[d] + diff - cbuf_sub[d];)
最佳答案
是的,OpenCV StereoBM 确实是基于 SAD。
当你在y方向滑动滑动窗口一行时,你不必重新计算整个窗口的SAD。相反,您将新行的 SAD 添加到窗口的 SAD。此外,您还可以从中减去不再位于窗口中的行的 SAD。
换句话说,一旦有了初始窗口的 SAD,就开始滑动窗口,只将新加入窗口的部分添加到 SAD 中,减去窗口中不再存在的部分,作为窗口已经通过了。
这正是 OpenCV 代码中所做的:
hsad[d] = hsad[d] + diff - cbuf_sub[d];
...
int currsad = sad[d] + hsad[d] - hsad_sub[d];
你对处理边界大小写的 sad[] 初始化代码感到困惑:
// initialize sums
for( d = 0; d < ndisp; d++ )
sad[d] = (int)(hsad0[d-ndisp*dy0]*(wsz2 + 2 - dy0));
第一个窗口的前半部分是这样初始化的。这意味着第一行之前的行的 hsad 值与第一行的 hsad 值相同。在这段代码之后是初始化窗口另一半的代码,其中 hsad 值已经来自有效行。
关于c++ - opencv stereobm,真的是基于SAD代价函数吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24507865/