2013-02-13 54 views
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); 
      } 
     } 
     } 
    } 
} 

目前的算法是非常缓慢的 - 为512×512和口罩大小的图像128x128它将不得不做512 * 512 * 384 * 41 = 4 127 195 136比较,这需要花费大量的时间在CPU上进行计算。其中一种选择是在GPU上进行计算,但是可以优化该算法以使其运行速度更快吗?我最终想要相对快速地获得一个很好的平滑梯度。

谢谢!

+0

与你的问题没有关系,但你可能想用'radius 2013-02-13 16:32:17

+0

使'罪'(alpha)&'cos(alpha)'表 - 这些功能缓慢。你也做错了一切!不要扫描*所有*像素,而是根据您的遮罩制作渐变遮罩(标记具有要标记距离值的像素)。你可以用随后的扩张来完成。 – 2013-02-13 16:35:00

+0

@Eddy_Em你应该充实你的渐变面具的建议,并将其作为答案。 – 2013-02-13 17:35:00

回答

0

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

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

1

那么,至于后续扩张。他们可以用修改过的算法完成。假设你在零背景上有一些掩码。把它放到你的图像上(通过放大零背景,这个舞台上的图像可能是一个unsigned shortunsigned int的数组,这取决于它的大小 - 我们需要将它的像素值放入距离中)。

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

在第一次迭代结束时free()第一个边界数组并运行新数组的第二次迭代,将2添加到邻居并填充下一个边界数组。

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


另一个变种是直接的算法,像你这样的。计算并存储掩码的边框。好。现在开始扫描扩展到图像大小掩码的所有像素。

如果像素值== 0,我们会遍历边界的所有像素,计算与它们的距离并存储最小距离。这将是渐变的价值。

该算法可以通过计算距离我们点的边界像素的距离来改善。为此,我们不仅应该存储边界像素的坐标,而且还应该存储来自掩模重心的角度。然后当扫描边界时,我们可以丢弃与当前图像点具有角度相等角度的像素,并掩盖重心±某个值(π/2?)。

另一种快速计算的方法是将sinuses &的cosinuses制作得很小,以致相邻成员之间的值可以忽略不计。这一步可能是从其中心成像的角度像素大小。甚至更大。


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