0

我有一种算法,可以根据到蒙版中最近像素的距离创建灰度渐变。我通过构造一个半径增加的圆并根据圆的像素对掩码中的所有像素进行采样来找到像素:

for (x = 0; x < width; x++){ 
   for (y = 0; y < height; y++) {
      bool pixelFound = false;
      for (radius = 0; radius < resolution, pixelFound == false; radius++) {
         for (alpha = 0; alpha < 2 * PI; alpha += 1/radius) {
            xx = x + cos(alpha)*radius;
            yy = y + sin(alpha)*radius;

            if ( MaskHasPixel(xx, yy) ) {
               pixelFound = true;
               gradient = 1 - Magnitude(xx-x, yy-y) / resolution;
               WriteGradientForPixel(x,y, gradient);
            }
         }
      }
   }
}

目前该算法非常慢 - 对于 512x512 的图像和 128x128 的掩码大小,它必须进行 512*512*384*41 = 4 127 195 136 次比较,这需要大量时间在 CPU 上进行计算。一种选择是在 GPU 上进行计算,但是否可以优化此算法以使其工作得更快?我希望最终获得相对较快的平滑渐变。

谢谢!

4

2 回答 2

1

好吧,至于随后的 dilations。它们可以通过修改后的算法来完成。假设您在零背景上有一些掩码。把它放到你的图像上(通过放大零背景,这个阶段的图像可能是一个数组unsigned shortunsigned int取决于它的大小——我们需要输入它的距离像素值)。

接下来的操作是距离计算。为了更快地做到这一点,首先我们找到掩码的边框并将其保存到坐标数组中。之后,我们遍历该数组并填充 8 个连接的非零像素,同时填充一个新的边框数组。

在第一次迭代结束时,第free()一个边界数组并使用新数组运行第二次迭代,将 2 放入邻居并填充下一个边界数组。

重复迭代,直到最后一个边框数组将有 0 个成员。


另一个变体是直接算法,就像你的一样。计算并存储掩码的边界。好的。现在开始扫描扩展至图像大小蒙版的所有像素。

如果像素值 ==0,我们遍历边界的所有像素,计算到它们的距离并存储最小距离。这将是梯度的值。

可以通过仅计算距我们点一侧的边界像素的距离来改进该算法。为此,我们不仅应该存储边界像素的坐标,还应该存储从蒙版重心到它们的角度。然后在扫描边界时,我们可以丢弃与当前图像点角度相等的像素,并掩码重心±某个值(π/2?)。

另一种更快地进行计算的方法是用一些步长将正弦和余弦制成表格,如此之小,以至于相邻成员之间的值可以忽略不计。这一步可以是图像角度从其中心的角度像素大小。甚至更大。


当然对于这个问题还有很多其他不同的优化方法,也许其中一些会更快。这是调查的问题。

于 2013-02-13T18:51:48.657 回答
0

我找到了一种让算法快 3 倍的方法: 1. 计算我的边框蒙版的几何中心。2. 计算从当前像素到上述中心的方向: dir = (center - pixel).normalized 3. 检查每一个朝向中心的像素是否是边界像素。4. 如果是,则搜索结束。5.如果没有找到靠近中心的边界像素,则使用原始较慢的方法。

另一种加快速度的方法是缩小原始图像的大小。这会有很大帮助。

于 2013-02-18T16:09:48.610 回答