Passing grayscale OpenCV image to an OpenGL texture

1.9k views Asked by At

I want to use a grayscale image generated in OpenCV in a GLSL shader.

Based on the question on OpenCV image loading for OpenGL Texture, I've managed to come up with the code that passes RGB image to the shader:

cv::Mat image; 
// ...acquire and process image somehow...

//create and bind a GL texture
glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture);

glTexImage2D(GL_TEXTURE_2D,     // Type of texture
    0,                 // Pyramid level (for mip-mapping) - 0 is the top level
    GL_RGB, // Internal colour format to convert to
    image.cols, image.rows, // texture size
    0,                 // Border width in pixels (can either be 1 or 0)
    GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
    GL_UNSIGNED_BYTE,  // Image data type
    image.ptr());        // The actual image data itself

glGenerateMipmap(GL_TEXTURE_2D);

and then in the fragment shader I just use this texture:

#version 330
in vec2 tCoord;

uniform sampler2D texture;

out vec4 color;

void main() {
    color = texture2D(texture, tCoord);
}

and it all works great.

But now I want to do some grayscale processing on that image, starting with cv::cvtColor(image, image, CV_BGR2GRAY);, doing some more OpenCV stuff to it, and then passing the grayscale to the shaders.

I thought I should use GL_LUMINOSITY as the colour format to convert to, and probably as the input image format as well - but all I'm getting is a black screen.

Can anyone please help me with it?

1

There are 1 answers

1
gemse On BEST ANSWER

input format

I'd use GL_RED, since the GL_LUMINANCE format has been deprecated

internalFormat

depends on what you want to do in your shader, although you should always specify a sized internal format, e.g. GL_RGBA8 which gives you 8 bits per channel. Although, with GL_RGBA8, the green, blue and alpha channels will be zero anyway since your input data only has a single channel, so you should probably use the GL_R8 format instead. Also, you can use texture swizzling:

GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_RED};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);

which will cause all channels to 'mirror' the red channel when you access the texture in the shader.