2011-04-30 208 views
5

我正在寻找一个快速,肮脏,非常有效的边缘检测着色器或边缘网格的视频应用程序。由于这将在移动设备上完成,因此我需要一些能够提高精度的性能。无论如何,我将模糊输出,而我所见过的所有边缘检测算法都倾向于通过将原始图像与模糊图像进行比较来完成。我认为这是造成大多数性能问题的模糊因素。GLSL边缘检测着色器最有效的方法

我有这样的工作的函数:

vec4 edge() 
{ 

    float K00 = -1.0; 
    float K01 = -2.0; 
    float K02 = -1.0; 
    float K10 = 0.0; 
    float K11 = 0.0; 
    float K12 = 0.0; 
    float K20 = 1.0; 
    float K21 = 2.0; 
    float K22 = 1.0; 

    vec2 ox = vec2 (0.0,0.0); 
    ox[0] = width; 
    vec2 oy = vec2 (0.0,0.0); 
    oy[1] = height; 

    float g00, g01, g02; 
    float g10, g11, g12; 
    float g20, g21, g22; 
    vec4 CC; 

    vec2 PP = TextureCoord - oy; 
    CC = texture2D(blurredFrame, vec2(PP-ox)); 
    g00 = getGrey(CC); 
    CC = texture2D(blurredFrame, vec2(PP)); 
    g01 = getGrey(CC); 
    CC = texture2D(blurredFrame, vec2(PP+ox)); 
    g02 = getGrey(CC); 


    PP = TextureCoord; 
    CC = texture2D(blurredFrame, vec2(PP-ox)); 
    g10 = getGrey(CC); 
    CC = texture2D(blurredFrame, vec2(PP)); 
    g11 = getGrey(CC); 
    CC = texture2D(blurredFrame, vec2(PP+ox)); 
    g12 = getGrey(CC); 

    PP = TextureCoord + oy; 
    CC = texture2D(blurredFrame, vec2(PP-ox)); 
    g20 = getGrey(CC); 
    CC = texture2D(blurredFrame, vec2(PP)); 
    g21 = getGrey(CC); 
    CC = texture2D(blurredFrame, vec2(PP+ox)); 
    g22 = getGrey(CC); 

    float sx = 0.0, sy = 0.0; 
    sx = sx + g00 * K00; 
    sx = sx + g01 * K01; 
    sx = sx + g02 * K02; 
    sx = sx + g10 * K10; 
    sx = sx + g11 * K11; 
    sx = sx + g12 * K12; 
    sx = sx + g20 * K20; 
    sx = sx + g21 * K21; 
    sx = sx + g22 * K22; 
    sy = sy + g00 * K00; 
    sy = sy + g01 * K10; 
    sy = sy + g02 * K20; 
    sy = sy + g10 * K01; 
    sy = sy + g11 * K11; 
    sy = sy + g12 * K21; 
    sy = sy + g20 * K02; 
    sy = sy + g21 * K12; 
    sy = sy + g22 * K22; 

    float dist = sqrt(sx * sx + sy * sy); 

    return dist > threshold ? vec4 (0,0,0,1) : vec4 (1,1,1,1); 
} 

我见过的所有例子都是这样,似乎专注于桌面平台 - 也参与和昂贵获得在iPhone或一个体面的帧率Android设备。这只适用于2d应用程序,速度是关键。

任何想法,使这个更有效率,或者更好的选择?感谢大家。

回答

4

不知道我是否知道不同的算法。

但是,一些建议浮现在脑海:

  1. 做比较DIST之前,不要采取的sqrt(),而不是比较DIST^2
  2. 看看你能不能优化访问模式的纹理负载。纹理内存访问模式可能会对性能产生重大影响。你想尽可能保持你的内存访问(即0,1,2,3,...),而不是随机的。
  3. 关闭mip贴图,或在您手动指定mip贴图级别的地方使用texture2DLod。
+0

谢谢。我唯一想到的其他事情就是从中删除“模糊”代码,并在缩小版本的图像上执行模糊处理,然后将该纹理传递到此代码的边缘检测部分。我认为这会加速模糊,但我会通过使用多次传球失去一些收益。 – akaru 2011-05-01 17:13:52

1

我有一个关于优化纹理样本夫妇的想法:

  1. 无需采样,而相应的系数为零 (K1 *)。
  2. 使用texture2DOffset代替texture2D。它接受恒定整数 偏移量,允许驱动程序 有效地预测您的访问模式更多 。
  3. 您正在对样本进行加权。您可以使用内置的线性过滤器来实现这一点。例如,对于 获取两个邻域 texels中的采样总和,可以在它们之间线性采样(仅 一次),并将 结果乘以2.此变体排除 先前的建议。
+1

谢谢。好的建议。我不认为texture2DOffset在opengles上可用,除非我只是实现了错误。 – akaru 2011-05-01 18:29:46

+0

@akaru。看起来你是正确的 - 在GL ES中没有'texture * Offset'功能。 – kvark 2011-05-01 18:53:55