Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convering OpenGL texture to OpenCV matrix

Tags:

c++

opencv

opengl

I've been looking for a way to convert an OpenGL texture into a OpenCV matrix type. I have found many guides which shows the conversion from OpenCV matrix to OpenGL texture, but sadly not the other way around. I have also read through this and its answer but it did not make me much wiser. I am writing in C++ and using OpenCV3.1 and OpenGL4.4.

EDIT: UPDATED CODE

main.cpp:

#include "CameraCapture.h"
#include "GUIMainWindow.h"
#include "glfw3.h"
#include "Texture.h"

using namespace std;

int main(int argc, char* argv[]) {

    if (!glfwInit()) {
        fprintf(stderr, "Failed to initialize GLFW \n");
        return -1;
    }

    glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
    GLFWwindow* window = glfwCreateWindow(1929, 1341, "OpenGL", NULL, NULL);

    if (window == NULL) {
        fprintf(stderr, "Failed to make GLFW window.");
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    CameraCapture *cc = new CameraCapture();
    cc->CameraCapture::AvailableCameras();
    GLuint texture = cc->CameraCapture::OpenCamera(0);

    glEnable(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, texture);

    drawGLTexture(window);

    Mat out = textureToMat(texture);
    namedWindow("Raytrix feed", WINDOW_AUTOSIZE);
    imshow("Raytrix feed", out);

    waitKey(0);

    return 0;

}

Texture.cpp:

Mat textureToMat(GLuint texture_id) {

    glBindTexture(GL_TEXTURE_2D, texture_id);
    GLenum texture_width, texture_height;

    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint*)&texture_width);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint*)&texture_height);

    unsigned char* texture_bytes = (unsigned char*)malloc(sizeof(unsigned char)*texture_width*texture_height * 4);

    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_bytes);

    return Mat(texture_height, texture_width, CV_8UC4, texture_bytes);

}

void drawGLTexture(GLFWwindow *window) {

    glColor3f(1.0f, 1.0f, 1.0f);

    glBegin(GL_TRIANGLES);
    glTexCoord2f(0, 1);
    glVertex2f(-1, -1);

    glTexCoord2f(1, 1);
    glVertex2f(1, -1);

    glTexCoord2f(0, 0);
    glVertex2f(-1, 1);

    glTexCoord2f(1, 1);
    glVertex2f(1, -1);

    glTexCoord2f(1, 0);
    glVertex2f(1, 1);

    glTexCoord2f(0, 0);
    glVertex2f(-1, 1);
    glEnd();

    glfwSwapBuffers(window);
    glfwPollEvents();

    glFlush();
    glFinish();

}

Header:

#ifndef TEXTURE_H
#define TEXTURE_H

#include "glew.h"
#include "glfw3.h"

#include <string>
#include <iostream>
#include <vector>
#include <opencv\highgui.h>
#include <opencv\cv.h>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

Mat textureToMat(GLuint textureID);
void drawGLTexture(GLFWwindow *window);

#endif /*!TEXTURE_H*/
like image 499
T. Soemod Avatar asked Oct 18 '22 05:10

T. Soemod


1 Answers

I've tested the code below and it seems to work. (Note the usage of GL_BGR in glGetTexImage()).

cv::Mat get_ocv_img_from_gl_img(GLuint ogl_texture_id)
{
    glBindTexture(GL_TEXTURE_2D, ogl_texture_id);
    GLenum gl_texture_width, gl_texture_height;

    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint*)&gl_texture_width);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint*)&gl_texture_height);

    unsigned char* gl_texture_bytes = (unsigned char*) malloc(sizeof(unsigned char)*gl_texture_width*gl_texture_height*3);
    glGetTexImage(GL_TEXTURE_2D, 0 /* mipmap level */, GL_BGR, GL_UNSIGNED_BYTE, gl_texture_bytes);

    return cv::Mat(gl_texture_height, gl_texture_width, CV_8UC3, gl_texture_bytes);
}
like image 142
sarasvati Avatar answered Oct 21 '22 05:10

sarasvati