【问题标题】:Luminance histogram calculation in GPU-android opengl es 3.0GPU-android opengl es 3.0中的亮度直方图计算
【发布时间】:2016-09-29 02:10:16
【问题描述】:

用于亮度直方图计算

我使用了 Brad Larson 的项目 GPU 图像 ios 中的代码。

他使用混合来计算直方图。

附加顶点和片段着色器

顶点着色器

#version 300 es 
in vec4 position;
out vec3 colorFactor;
const vec3 W = vec3(0.299, 0.587, 0.114);
void main() 
  {
      float luminance = dot(position.xyz, W);
      colorFactor = vec3(1.0, 1.0, 1.0);
      gl_Position = vec4(-1.0 + (luminance *  0.00784313725), 0.0, 0.0, 1.0);
      gl_PointSize = 1.0;
   } ;

片段着色器

#version 300 es 
const lowp float scalingFactor = 1.0 / 256.0;
in lowp vec3 colorFactor;
out vec4 gl_FragColor;\n"+
void main() 
  {
     gl_FragColor = vec4(colorFactor * scalingFactor , 1.0);
  };

我使用了一个附加到 FBO 的 256x1 纹理,并将像素作为输入传递给顶点着色器。 纹理定义如下

GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);

GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA,
                256, 1, 0, GLES30.GL_RGBA,
                GLES30.GL_UNSIGNED_BYTE, null);

我的 onDrawFrame 是这样的

GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
GLES30.glBlendEquation(GLES30.GL_FUNC_ADD);
GLES30.glBlendFunc(GLES30.GL_ONE, GLES30.GL_ONE);
GLES30.glEnable(GLES30.GL_BLEND);

filterPositionAttribute = mshader2.getHandle("position");


GLES30.glVertexAttribPointer(filterPositionAttribute, 4, GLES30.GL_UNSIGNED_BYTE,false,60, PixelBuffer);
GLES30.glEnableVertexAttribArray(filterPositionAttribute);


GLES30.glDrawArrays(GLES30.GL_POINTS, 0, mViewportWidth * mViewportHeight /16);

我将使用 16 个像素中的 1 个进行直方图计算。

现在我正在获取图表和值。 但是当使用matlab和irfanview等其他软件进行验证时,就出现了偏差。

附加在excel中创建的图表 values from my application

verified values using matlab

这种变化是预期的还是我犯了一些错误。 谁能帮忙,提前谢谢

【问题讨论】:

  • 你的“60”从何而来?这使得它每 15 像素而不是每 16 像素一次。
  • 另外,我建议添加 0.5 以确保您在像素中间绘制 GL_POINT。此外,常数应该是 1 / 256.0 而不是 1 / 255.0。 gl_Position = vec4(-1.0 + (0.5 + luminance) * (1.0 / 256.0), 0.5, 0.0, 1.0);
  • @246tNt 感谢您的建议,但即使使用 gl_Position = vec4(-1.0 + (0.5 + 亮度) * (1.0 / 256.0), 0.5, 0.0, 1.0);与 matlab 中的计算相比,我得到了变化
  • 你确定你“PixelBuffer”的格式吗?
  • PixelBuffer 是一个字节缓冲区,我使用 GLES30.glReadPixels(0, 0, mViewportWidth, mViewportHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, PixelBuffer);我将这个像素输入顶点着色器

标签: android opengl-es glsl opengl-es-3.0


【解决方案1】:

我正在使用 C 和桌面 GL,但这里是它的要点:

顶点着色器

#version 330
layout (location = 0) in vec2 inPosition;
void main()
{
    int x = compute the bin (0 to 255) from inPosition;

    gl_Position = vec4(
        -1.0 + ((x + 0.5) / 128.0),
        0.5,
        0.0,
        1.0
    );
}

片段着色器

#version 330
out vec4 outputColor;
void main()
{
    outputColor = vec4(1.0, 1.0, 1.0, 1.0);
}

初始化:

glGenTextures(1, &tex);
glGenFramebuffers(1, &fbo);

glActiveTexture(GL_TEXTURE0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1);

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);

绘图:

/* Upload data */
glBufferData(GL_ARRAY_BUFFER, num_input_data * 2 * sizeof(float), input_data_ptr, GL_STREAM_DRAW);

/* Clear buffer */
const float zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
glClearBufferfv(GL_COLOR, 0, zero);

/* Init viewport */
glViewport(0, 0, 256, 1);

/* Draw */
glDrawArrays(GL_POINTS, 0, num_input_data);

为了简单起见,我只为生成的缓冲区添加了初始化代码,所有的 VBO/VAO 初始化/绑定都被跳过了

【讨论】:

  • 我可以使用 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1);在 opengles 3.0 中,我一直在使用 glTeximage2d。还有如何使用 glreadpixel 验证结果
  • 似乎存在:developer.android.com/reference/android/opengl/…。至于回读:glReadPixels(0, 0, 256, 1, GL_RED, GL_FLOAT, buffer) 应该可以工作。
  • 我已验证我的设备支持 GL_EXT_COLOR_BUFFER_FLOAT。所以现在我的代码是 GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA32F, 256, 1, 0, GLES30.GL_RGBA, GLES30.GL_FLOAT, null);而对应的glreadpixel为GLES30.glReadPixels(0, 0, 256, 1, GLES30.GL_RGBA, GLES30.GL_FLOAT, PixelBufferTest);其中 PixelBufferTest 是 ByteBuffer PixelBufferTest = ByteBuffer.allocateDirect( 16 * 256 * 1);但仍然无法正常工作。有什么想法吗?
  • 32 位纹理工作正常,我使用 GL_R32F 存储直方图计数。所以现在我考虑每个像素进行直方图计算。但即使是现在,当我与在 irfanview 或其他一些软件中完成的直方图计算进行比较时,它似乎也存在偏差。即每个 bin 中的像素总数是不同的。你还有什么建议吗?
  • 那么您确定他们使用与您相同的加权 (W) 系数吗?他们也可能会考虑色彩空间( sRGB )或类似的东西......在纯 C 的 CPU 上自己做作为参考,这应该与您的 GPU 实现相匹配。
猜你喜欢
  • 2013-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 2017-01-13
相关资源
最近更新 更多