Ask Your Question
1

Opencv mat as opengl texture

asked 2018-05-30 05:05:55 -0600

Shivanshu gravatar image

updated 2018-05-30 05:07:21 -0600

I am trying to imply opecv operation(for vision intelligence) in my opengl project.I am trying to figure out how shall i phrase cv::mat to unsigned char*(which is taken by opengl for texture)..I dont know how opencv is allocating an image file with what kind of memory scheme...how it is keeping mat data(specially an RBG image)in memory so than i can create a phrasor which can phrase opencv Mat for opengl Texture.I cant map how to do it,b'cause i cant find a place where I can study about opencv memory implementation for cv::mat ,need help,Thankyou!!

edit retag flag offensive close merge delete

Comments

1

it's as simple as: unsigned char * d = mat.data;

you probably don't need to convert from bgr to rgb, there's a flag in the opengl call for that.

berak gravatar imageberak ( 2018-05-30 05:09:08 -0600 )edit

show the opengl texture code, please !

berak gravatar imageberak ( 2018-05-30 05:09:42 -0600 )edit

@berak always like before,thank you for you answer.Though did you mean the shader??And one more question..simply type assigning image to chars??what about the format favorable to opengl??wont be voilated,I mean the way opengl keep stride of bgr values and each stride of certain bytes...Things like that

Shivanshu gravatar imageShivanshu ( 2018-05-30 05:22:02 -0600 )edit

not the shader, the upload code, glTexSomething, whatever you use.

also, opencv uses continuous memory, no padding needed, so the stride is just width*3

berak gravatar imageberak ( 2018-05-30 05:30:09 -0600 )edit
1

https://bpaste.net/show/c71815322946 I was using STB library from github for image file phrasing...

Shivanshu gravatar imageShivanshu ( 2018-05-30 05:54:40 -0600 )edit

yea, that part.

does it work ?

lol, you have width & height wrong (and maybe either format or internalFormat should be GL_BGR, my memory is hazy here !)

oh, and stbi_image_free(image); looks VERY wrong to me ! (Mat img will release the data on it's own, when leaving your function)

what is "file phrasing" ?

berak gravatar imageberak ( 2018-05-30 06:01:09 -0600 )edit

well sorry about ' stbi_image_free(image);'I really did't looked about that!Its seems a lot of mistakes i made on b paste!

Shivanshu gravatar imageShivanshu ( 2018-05-30 06:08:29 -0600 )edit

just don't try to release it twice

berak gravatar imageberak ( 2018-05-30 06:32:03 -0600 )edit

Though i managed to bring something on my screen...but it seems blue channel spreads out its kingdome little more over texture colours...I am reading a png format

Shivanshu gravatar imageShivanshu ( 2018-05-30 07:00:33 -0600 )edit
1

@Shivanshu -- Are you still having trouble? Don't forget that the Mat has a BGR layout by default. I mean, you must be seeing something, perhaps with the red and blue channels swapped, right? Create a minimal code that calls glTexImage2D and paste it to GitHub as a Gist. I don't trust any other code source.

Don't make your texture have an alpha channel if it doesn't need it; every byte should count.

sjhalayka gravatar imagesjhalayka ( 2018-05-30 14:04:51 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-05-30 23:49:14 -0600

This is my code for reading image from camera and display(With mirrored) with GLFW+OpenGL. May it help you.

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.h"
#include <iostream>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>


using namespace cv;


void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
unsigned char* cvMat2TexInput(Mat& img);


int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // for Mac OSX
#endif

    VideoCapture cap(0);
    if (!cap.isOpened())
    {
        std::cout << "Camera not opened!" << std::endl;
        return -1;
    }
    Mat frame;
    cap >> frame;
    int width = frame.cols;
    int height = frame.rows;
    unsigned char* image = cvMat2TexInput(frame);

    // glfw window creation
    GLFWwindow* window = glfwCreateWindow(width, height, "frame", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    // glad: load all OpenGL function pointers
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }


    Shader ourShader("shader.vert", "shader.frag");
    float vertices[] = {
        //     Position       TexCoord
        -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, // top left
        1.0f,   1.0f, 0.0f, 1.0f, 1.0f, // top right
        -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // below left
        1.0f,  -1.0f, 0.0f, 1.0f, 0.0f  // below right 
    };
    // Set up index
    unsigned int indices[] = {
        0, 1, 2,
        1, 2, 3
    };

    unsigned int VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);    
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    while(!glfwWindowShouldClose(window))
    {
        cap >> frame;
        image = cvMat2TexInput(frame);
        if(image)
        {
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
        }
        else
        {
            std::cout << "Failed to load texture." << std::endl;
        }

        processInput(window);
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        // Draw Rectangle
        ourShader.use();
        glBindTexture(GL_TEXTURE_2D, texture);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}


void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    (void)window;
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

unsigned char* cvMat2TexInput(Mat& img)
{
    cvtColor(img, img, COLOR_BGR2RGB);
    flip(img, img, -1);
    return img.data;
}
edit flag offensive delete link more

Comments

What if i read image from different extension like jpg,jpeg,png or bmp??Do i have to change glTex2Dparameter for that??I choosed 512x512 version it worked well but for higher resolution i see unusual lines overlaying texture

Shivanshu gravatar imageShivanshu ( 2018-06-01 02:36:12 -0600 )edit

I am also thinking about what changeg i have to make if i convert image from like BGR2GRAY,or BGR2RGB or something like that..

Shivanshu gravatar imageShivanshu ( 2018-06-01 02:38:51 -0600 )edit

Image formats like jpg, png etc. does not matters. It only depends on whether OpenCV support that format. But your image may be not of CV_8UC3, for this situation you need to modify parameters of glTexImage2D. You said you occurred trouble with high resolution image, which I have no idea, I have no experience of this situation. I have trouble with your second comment, I can't figure out what you means. Can you explain it more concisely?

sparkecho gravatar imagesparkecho ( 2018-06-02 03:21:54 -0600 )edit

What I am saying in my second comment is about is if i convert input image to Grayscale image of 8-bit single channel matrix then what should do with my glTexImage2D parameters...

Shivanshu gravatar imageShivanshu ( 2018-06-03 09:02:27 -0600 )edit

As far as I know, there is no direct method to just display a one-channel grayscale image. (If someone know please tell me, thanks.) But you can extend your one-channel image to 3-channel RGB image or 4-channel RGBA image. To extend your one-channel grayscale image you just need to repeat it 3 times. With OpenCV you can use function merge to do this. Details:

vector<Mat> channels;
for(int i = 0; i < 3; i++)
    channels.push_back(gray);
Mat bgr_image;
merge(channels, bgr_image);

You can try it, I think it works.

sparkecho gravatar imagesparkecho ( 2018-06-03 09:19:52 -0600 )edit
1

To display BGR in OpenGL correctly, there is another way (this way is more efficient and easy to use): Just change

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

to:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, image);
sparkecho gravatar imagesparkecho ( 2018-06-04 10:33:29 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-05-30 05:05:55 -0600

Seen: 6,833 times

Last updated: May 30 '18