1
votes

I want to load the opencv::mat images with alpha channel to OpenGL texture.

With the help of following posts I could manage to load RGB images into an OpenGL texture from opencv::mat.

https://stackguides.com/questions/16809833/opencv-image-loading-for-opengl-texture

https://stackguides.com/questions/9097756/converting-data-from-glreadpixels-to-opencvmat/9098883#9098883

But when I try to load the image with an alpha channel, there is a problem.

Here is how the glTexImage2D function is called.

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

Also, before rendering, I enable the blending by using glEnable(GL_BLEND);

If I specifyinput image format and internal color format to both be GL_RGBA / GL_BGRA, I get a segmentation fault, but if I set either of them or both of them to GL_RGBA_INTEGER, at least I can see the window, but just blank.

I can change the transparency and accordingly the window become more or less transparent, but there is no image in it. There is an image in the cv::mat as i can see it using cv::imshow, but somehow there seems a problem passing it to the OpenGL texture.

Could any one suggest something I might be missing. Thanks in advance.

P.S : I am new to OpenGL, I would really appreciate if explained with smallest detail.. :P

1
The _INTEGER pixel transfer formats do not make a lot of sense when used together with GL_UNSIGNED_BYTE, these are for special new packed integer formats like UNSIGNED_SHORT_5_5_5_1 (16-bits, where each component is a fractional portion of an integer type). Try using UNSIGNED_INT_8_8_8_8 instead of GL_UNSIGNED_BYTE if you are going to use GL_BGRA_INTEGER, this at least makes sense.Andon M. Coleman
Why are you using integer image formats to begin with? Traditional fixed-point / unsigned normalized is almost certainly what you want, you would be well aware why/when you needed an actual integer format.Andon M. Coleman
Sorry for getting back so late. I was making mistake in the first step only, while reading the image in opencv. Once i corrected it, i could use GL_BGRA only. Thanksformjk
can you post correct code? I am experiencing a similar problem..nkint

1 Answers

0
votes

I got it working on my computer, able to load and display png texture.

The code in the question is adapted from the last answer in the following link.

OpenCV image loading for OpenGL Texture

I post my working code (also adapted from the code in the aforementioned link) below

GLuint Texture;

cv::Mat image = cv::imread("textures/trashbin.png", -1);

cv::flip(image, image, 0);
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// Set texture clamping method
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


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

Pay attention to 3 points:

  • The -1 in the imread call at the second line. It tells OpenCV to load the alpha channel. I believe this is where the questioner had the problem.
  • The GL_RGBA and GL_BGRA in the last function call.
  • cv::flip(image, image, 0); was not necesssary for me, I actually had it commented out in my project. The reason might be I got the UV coordinates flipped in the first place.