opencv stereobm,它真的基于SAD成本函数

use*_*060 3 c++ opencv

我正在尝试增强stereobm(Opencv立体声块匹配).他们声称该算法使用SAD cost_function方法.(Abos不同的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]  
Run Code Online (Sandbox Code Playgroud)

那么,为什么他们用*(wsz2 + 2-dy0)进行乘法运算?

以及为什么他们从hsad [d]中减去cbuf_sub [d](hsad [d] = hsad [d] + diff - cbuf_sub [d];)

小智 5

是的,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];
Run Code Online (Sandbox Code Playgroud)

您对处理边界情况的sad []初始化代码感到困惑:

    // initialize sums
    for( d = 0; d < ndisp; d++ )
        sad[d] = (int)(hsad0[d-ndisp*dy0]*(wsz2 + 2 - dy0));
Run Code Online (Sandbox Code Playgroud)

这是第一个窗口的前半部分初始化的方式.这意味着第一行之前的行的hsad值与第一行的hsad具有相同的值.在此代码之后,代码初始化窗口的另一半,其中hsad值已经来自有效行.