GLSL和GPU片段着色器执行中的求和区域表

Kai*_*yra 2 shader gpu opengl-es glsl

我正在尝试计算我在GPU内存中的纹理(相机捕获)的积分图像(也称为求和区域表),目标是计算所述图像的自适应阈值.我正在使用OpenGL ES 2.0,还在学习:).

我用一个简单的高斯模糊着色器(垂直/水平通过)进行了测试,它工作正常,但我需要一个更大的可变平均面积来获得满意的结果.

我之前在CPU上实现了该算法的一个版本,但是我对如何在GPU上实现它有点困惑.我尝试对每个片段做一个(完全不正确的)测试,例如:

#version 100
#extension GL_OES_EGL_image_external : require

precision highp float;
uniform sampler2D           u_Texture;      // The input texture.
varying lowp vec2           v_TexCoordinate;    // Interpolated texture     coordinate per fragment.
uniform vec2                u_PixelDelta;           // Pixel delta

void main()
{
    // get neighboring pixels values
    float center = texture2D(u_Texture, v_TexCoordinate).r;
    float a = texture2D(u_Texture, v_TexCoordinate + vec2(u_PixelDelta.x * -1.0, 0.0)).r;
    float b = texture2D(u_Texture, v_TexCoordinate + vec2(0.0, u_PixelDelta.y * 1.0)).r;
    float c = texture2D(u_Texture, v_TexCoordinate + vec2(u_PixelDelta.x * -1.0, u_PixelDelta.y * 1.0)).r;

    // compute value
    float pixValue = center + a + b - c;


    // Result stores value (R) and original gray value (G)
    gl_FragColor = vec4(pixValue, center, center, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

然后是另一个着色器,以获得我想要的区域,然后获得平均值.这显然是错误的,因为有多个执行单元同时运行.

我知道,在GPU计算前缀和共同的方法是做两通(垂直/水平,因为这里讨论在此线程或这里),但是是不是有问题,这里有一个数据依赖于前一个(顶部或左侧)单元格的每个单元格?

我似乎无法理解GPU上的多个执行单元处理不同片段的顺序,以及双通滤波器如何解决该问题.举个例子,如果我有这样的值:

2 1 5
0 3 2
4 4 7
Run Code Online (Sandbox Code Playgroud)

两个pass应该给(第一列然后是行):

2 1 5          2 3 8
2 4 7     ->   2 6 13
6 8 14         6 14 28
Run Code Online (Sandbox Code Playgroud)

作为一个例子,我怎么能确定值[0; 2]将被计算为6(2 + 4)而不是4(0 + 4,如果还没有计算0)?

此外,据我所知,片段不是像素(如果我没有弄错),如果我使用从传递的完全相同的坐标,我在第一遍中的一个纹理中存储的值是否会在另一个传递中相同顶点着色器,还是会以某种方式插值?

Bra*_*son 5

Tommy和Bartvbl解决了有关求和区域表的问题,但您的自适应阈值的核心问题可能不需要.

作为我的开源GPUImage框架的一部分,我已经做了一些使用OpenGL ES 优化大半径模糊的实验.通常,增加模糊半径导致纹理采样和每像素计算的显着增加,伴随着减速.

但是,我发现对于大多数模糊操作,您可以应用令人惊讶的有效优化来限制模糊样本的数量.如果在模糊之前对图像进行下采样,在较小的像素半径(半径/下采样因子)处进行模糊,然后线性上采样,则可以得到模糊的图像,该图像相当于在更大的像素半径处模糊的图像.在我的测试中,这些下采样,模糊,然后上采样的图像看起来几乎与基于原始图像分辨率模糊的图像相同.实际上,精度限制可能导致在原始分辨率下完成的较大半径模糊,使图像质量超过一定大小,其中下采样保持适当的图像质量.

通过调整下采样因子以使下采样模糊半径保持恒定,可以在模糊半径增加的情况下实现接近恒定时间的模糊速度.对于自适应阈值,图像质量应该足以用于比较.

我在上面链接框架的最新版本中以高斯和盒子模糊使用这种方法,因此如果您在Mac,iOS或Linux上运行,您可以通过尝试其中一个示例应用程序来评估结果.我有一个基于使用此优化的盒子模糊的自适应阈值操作,因此您可以查看结果是否符合您的要求.