快速找到2d数组的矩形区域内的最大值

时间:2016-08-04 05:23:55

标签: c++ arrays algorithm optimization

我有一个深度值的二维数组,需要一种快速的方法来找到给定矩形区域内的最大值。许多矩形将针对给定的深度缓冲区进行测试,因此可以接受合理的预处理步骤。

天真的方法是扫描矩形中的每个像素,跟踪最大值,需要宽度*高度迭代。

首先创建深度缓冲区的四叉树,其中每个父节点包含其子节点的最大值,复杂度可以减少到大约宽度+高度迭代。这种方法很好,但我想知道它是否可以更快地完成。

我给出了一个通过使用线性时间预处理here找到平均值而不是恒定时间内的最大值的方法示例。

有没有人知道找到最大值的类似技术?

2 个答案:

答案 0 :(得分:1)

,您可以概括平均值的技巧,但仅适用于小颜色深度,例如8位深度(0-255)。假设你有 k 颜色(或不同的深度值)。

供您参考,以下是通过积分图像Viola/Jones CVPR 2001平均计算矩形的一个很好的解释,见2.1节。

我的广义算法是预先计算具有维数k的向量的积分,颜色/深度值的出现频率。从这个向量中,您可以采用与技巧相同的差异来计算均值。这不仅为您提供矩形区域内的最大值,而且实际上是恒定时间内该矩形内直方图的矢量。当然,直方图允许您提取最大值(或最小值或其他分位数)。

时间和内存要求当然会随着颜色的数量而增长,我认为复杂度类是 O(k)用于查找和 O(k * width * height)用于预先计算。

(如果以前使用过我的想法,我会很感兴趣。)

答案 1 :(得分:0)

通过添加零将数组填充到2的平方幂。然后将其金字塔化为堆栈,每次在每个维度上缩小2倍。在每个级别,每个元素的值等于金字塔中下一个最大数组中的4个对应元素的最大值。这将在填充数组大小的顶部占用额外的1/3存储空间,如mip-maps那样。

编写一个递归函数,该函数接受给定数组级别的单个元素,并检查查询区域是否覆盖了它所涵盖的边界。如果没有,则它检查与查询区域重叠的下一个最大数组中的每个区域,返回每个区域的递归计算最大值。

的伪代码:

 int getMax(Rect query_rect, int level, int level_x, int level_y)
 {
      int level_factor = 1 << level;
      // compute the area covered by this array element:
      Rect level_rect(level_x * level_factor, level_y * level_factor,
          (level_x + 1) * level_factor, (level_y + 1) * level_factor);

      // if the regions don't overlap then ignore:
      if(!query_rect.intersects(level_rect))
          return -1;

      // query rect entirely contains this region, return precomputed max:
      if(query_rect.contains(level_rect))
          return pyramid[level][level_x][level_y];

      if(level == 0)
          return -1;  // ran out of levels

      int max = getMax(query_rect, level - 1, level_x * 2, level_y * 2);
      max = maxValue(max, getMax(query_rect, level - 1, (level_x * 2) + 1, level_y * 2);
      max = maxValue(max, getMax(query_rect, level - 1, level_x * 2, (level_y * 2) + 1);
      max = maxValue(max, getMax(query_rect, level - 1, (level_x * 2) + 1, (level_y * 2) + 1);

      return max;
 }

最初在顶层(金字塔中的顶点1x1数组)调用它:

 int max = getMax(query_rect, 10, 0, 0);

查询矩形的最小尺寸,在其下面迭代所有元素会更便宜。您可以对此进行调整以使用非正方形数组,在递归时,它只需要对每个级别的数组大小进行一些额外的测试。