4

For Luminace histogram calculation

I have used the code from the project GPU image ios by Brad Larson.

He has used blending for Histogram calculation.

Attaching the Vertex and Fragment shader

Vertex shader

#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;
   } ;

Fragment Shader

#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);
  };

i have used a 256x1 texture attached to an FBO and Pass in the pixel as input to vertex shader. Texture is defined as follows

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);

And my onDrawFrame goes like this

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);

i will be using 1 pixel out of 16 for histogram calculation.

Now i am getting the graph and values. But when verified using matlab and other software like irfanview ,it appears deviated.

Attaching the graph created in excel values from my application

verified values using matlab

is this variation expected or i am making some mistakes. Could anybody help ,thanks in advance

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Where does your "60" comes from ? That makes it once every 15 pixels and not every 16 pixels. – 246tNt May 31 '16 at 07:31
  • Also, I'd suggest to add 0.5 to make sure your draw the GL_POINT in the middle of the pixel. Also, the constant should be 1 / 256.0 and not 1 / 255.0. `gl_Position = vec4(-1.0 + (0.5 + luminance) * (1.0 / 256.0), 0.5, 0.0, 1.0);` – 246tNt May 31 '16 at 08:02
  • @246tNt Thanks for the suggestion,but even after using gl_Position = vec4(-1.0 + (0.5 + luminance) * (1.0 / 256.0), 0.5, 0.0, 1.0); i am getting variation when compared with the calculation in matlab – vishnu dinakaran May 31 '16 at 09:54
  • Are you sure of the format of you "PixelBuffer" ? – 246tNt May 31 '16 at 09:56
  • PixelBuffer is a bytebuffer and i am getting the pixels by using GLES30.glReadPixels(0, 0, mViewportWidth, mViewportHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, PixelBuffer); This pixel i feed into the vertex shader – vishnu dinakaran May 31 '16 at 10:02
  • Mmmm, I don't see anything wrong. I implemented a similar histogram just last weekend and it worked as expected. Are you sure of the matlab reference ? (from the histogram it just looks like a gray image ?). Also, as a side note, you don't need colorFactor at all, you can remove it completely. – 246tNt May 31 '16 at 12:11
  • Did you do a `glViewport(0, 0, 256, 1)` before rendering ? – 246tNt May 31 '16 at 12:13
  • yes, i have used that GLES30.glViewport(0, 0, 256, 1); – vishnu dinakaran May 31 '16 at 12:16
  • For your histogram calculation,did you consider every pixel for histogram calculation? – vishnu dinakaran May 31 '16 at 12:17
  • Yes, I used all my input data in my application. And you should fix your 60 into 64 btw if you want every 16 pixels. – 246tNt May 31 '16 at 12:18
  • you did this in android? did you use a 16 bit texture? – vishnu dinakaran May 31 '16 at 12:21
  • No this was on desktop OpenGL but using the same algorithm principles. Although now that you mention it, I'm using a floating point R32F texture for the result and not a GL_RGBA one. Because in a single byte you can only store up to 255 "hits" in a single bin, which might not be enough for your image. – 246tNt May 31 '16 at 12:25
  • can i use R32F in opengl es 3.0 ,in that case i can consider every pixels in my image. – vishnu dinakaran May 31 '16 at 12:28
  • Looks like R32F is not "color renderable" in OpenGL ES. But R32UI is. So you could use that to allow for a much wider range. – 246tNt May 31 '16 at 12:44
  • (As a note to my previous comment, if you have GL_EXT_color_buffer_float you can use R32F as a render target) – 246tNt May 31 '16 at 13:01
  • For using R32UI i should change only GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, 256, 1, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null); wrt? and how to get back the result using glreadpixel – vishnu dinakaran May 31 '16 at 13:03
  • @246tNt Could you share the portion of your histogram calculation code that does the R32F part (32bit red component).i am having issues when trying to change it to 32 bit – vishnu dinakaran Jun 01 '16 at 05:03

1 Answers1

2

I'm using C and desktop GL, but here's the gist of it :

Vertex shader

#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
    );
}

Fragment shader

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

Init:

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);

Drawing :

/* 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);

For brievety I only put the init code for the resulting buffer, all the VBO/VAO init/binding has been skipped

246tNt
  • 2,122
  • 1
  • 16
  • 20
  • can i use glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1); in opengles 3.0 ,i have been using glTeximage2d.Also how to verify the result using glreadpixel – vishnu dinakaran Jun 01 '16 at 08:58
  • Seem to exist : https://developer.android.com/reference/android/opengl/GLES30.html#glTexStorage2D%28int,%20int,%20int,%20int,%20int%29 . As for the readback : `glReadPixels(0, 0, 256, 1, GL_RED, GL_FLOAT, buffer)` should work. – 246tNt Jun 01 '16 at 09:10
  • i had verified that my device supports GL_EXT_COLOR_BUFFER_FLOAT. so right now my code is GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA32F, 256, 1, 0, GLES30.GL_RGBA, GLES30.GL_FLOAT, null); and the corresponding glreadpixel is GLES30.glReadPixels(0, 0, 256, 1, GLES30.GL_RGBA, GLES30.GL_FLOAT, PixelBufferTest); where PixelBufferTest is ByteBuffer PixelBufferTest = ByteBuffer.allocateDirect( 16 * 256 * 1); but still not working. Any idea? – vishnu dinakaran Jun 03 '16 at 10:35
  • 32 bit texture is working fine,i had used GL_R32F for storing histogram count. so now i consider every pixel for histogram calculation. But even now when i compare with the histogram calculation done in irfanview or some other software, it appears deviated. ie total number pixel count in each bin is different. Do u have any other suggestion? – vishnu dinakaran Jun 13 '16 at 12:02
  • Well are you sure they use the same weighting ( W ) coefficients than you do ? They also might consider color space ( sRGB ) or things like that ... do it yourself on the CPU in plain C as a reference and that should match your GPU impl. – 246tNt Jun 13 '16 at 14:12