平均计算速度更快(openCV,C ++)

时间:2016-02-10 09:26:11

标签: c++ performance opencv mean

我正在计算C ++中图像内多个平方区域的平均值。因此,我在图像上移动一个平方区域,并使用openCV“mean”函数计算平均值,但用std替换它。平均计算(见下文),这意外地更快。然而,在Android设备上需要大约8ms,因为平均计算大约需要400次(每次平均计算需要大约0.025ms)

uchar rectSize = 10;
Rect roi(0,0,rectSize, rectSize);
int pxNumber = rectSize * rectSize;
uchar value;

//Shifting the region to the bottom
for(uchar y=0; y<NumberOfRectangles_Y; y++)
{
    p = outBitMat.ptr<uchar>(y);
    roi.x = rectSize;

    //Shifting the region to the right
    for(uchar x=0; x<NumberOfRectangles_X; x++, ++p)
    {
        meanCalc(normalized(roi),rectSize, pxNumber, value);
        roi.x += rectSize;
    }

    roi.y += rectSize;
}


 void meanCalc(const cv::Mat& normalized, uchar& rectSize, int& pxNumber, uchar& value)
{
   for(uchar y=0; y < rectSize; y++)
   {
      p = normalized.ptr<uchar>(y);

      for(uchar x=0; x < rectSize; x++, ++p)
      {
        sum += *p;
      }
   }
   value =  sum / (float)pxNumber;
}

有没有办法加速图像内每个矩形窗口的平均计算?我可以做一些像素前排序,只计算一次平均值并加快速度吗?

提前致谢

更新

根据用户6502的答案和使用总和表,我得出以下结论:

Mat tab;
integral(image,tab);
int* input = (int*)(tab.data);
value = (input[yStart*tabWidth + xStart] + input[(yStart+rectSize)*tabWidth + xStart+rectSize]
                   - input[yStart*tabWidth + xStart+rectSize] - input[(yStart+rectSize)*tabWidth + xStart]) / (double)pxNumber;

因此这个功能需要几乎相同的时间。在计算大量重叠区域时,总和表是否有用?因为在我的情况下,我只触摸每个像素进行一次计算。

2 个答案:

答案 0 :(得分:6)

您可以通过预先计算“summed area table”来计算恒定时间内任何矩形的平均值(与矩形大小无关)。

您需要计算一个表格,其中元素(i, j)是从(0, 0)(i, j)的矩形中所有原始数据的总和,这可以通过一次传递完成数据

获得该表后,(x0, y0)(x1, y1)之间的值之和可以在恒定时间内计算:

tab(x0, y0) + tab(x1, y1) - tab(x0, y1) - tab(x1, y0)

要了解算法是如何工作的,首先要考虑一维情况更容易:在恒定时间内计算从v[x0]v[x1]的值的总和,您可以预先计算一个表

st[0] = v[0];
for (int i=1; i<n; i++) st[i] = st[i-1] + v[i];

然后您可以使用差异st[x1] - st[x0]来了解原始数据的任何间隔的总和。

该算法确实可以轻松扩展到n维度。

此外,初看起来可能并不明显,但可以为多核架构实现求和区域表的预计算,以利用并行执行。

对于2d,简单分解是考虑计算2d和表与计算每行上的1d和表,然后计算结果上每列的1d和表相同。

答案 1 :(得分:0)

您可以使用Simd Library的函数menCalc优化版本:

SIMD_API void SimdValueSum(const uint8_t * src, size_t stride, 
    size_t width, size_t height, uint64_t * sum);

它更快,因为使用不同的SIMD,如SSE,AVX等。