2016-07-26 188 views
-1

我遇到了一些關於glTexImage2D()glGetTexImage()的問題。使用glTexImage2D和glGetTexImage的一些問題

在我的代碼中,我嘗試使用OpenCV的imread()加載圖像,將其轉換爲具有texture_id句柄的紋理格式,然後再次將其轉換回矩陣類型(OpenCV的Mat)。一路上我的圖像數據似乎丟失,image.data返回NULL。

我懷疑問題出在我執行matToTexture()的地方。

我在C++中使用Visual Studio 15編寫,並使用OpenCV 3.1和OpenGL 4.4。

Texture.cpp:

#include "Texture.h" 

Mat textureToMat(GLuint textureID); 
GLuint matToTexture(Mat image); 

GLuint matToTexture(Mat image) { 

    GLuint texture_id; 

    if (image.empty()) { 
     cout << "Image empty." << endl; 
    } 

    else { 

     glGenTextures(1, &texture_id); 
     glBindTexture(GL_TEXTURE_2D, texture_id); 

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

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 

     glTexImage2D(GL_TEXTURE_2D, 
      0, 
      GL_RGB, 
      image.cols, 
      image.rows, 
      0, 
      GL_BGR, 
      GL_UNSIGNED_BYTE, 
      image.ptr()); 

    } 

    return texture_id; 
} 

Mat textureToMat(GLuint texture_id) { 

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

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

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

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

    Mat out(texture_height, texture_width, CV_8UC3, texture_bytes); 

    free(texture_bytes); 

    return out; 

} 

和標題Texture.h:

#ifndef TEXTURE_H 
#define TEXTURE_H 

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

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

using namespace std; 
using namespace cv; 

Mat textureToMat(GLuint textureID); 
GLuint matToTexture(Mat image); 

#endif /*!TEXTURE_H*/ 

和呼叫:

#include "Texture.h" 

int main(){ 

    glfwInit(); 
    glewExperimental = GL_TRUE; 
    glewInit(); 

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 

    GLFWwindow* offscreen_context = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr); 
    glfwMakeContextCurrent(offscreen_context); 

    Mat dummy = imread("mini.jpg", CV_LOAD_IMAGE_COLOR); 

    GLuint tex = matToTexture(dummy); 

    glBindTexture(GL_TEXTURE_2D, tex); 

    Mat some = textureToMat(tex); 

    while (!glfwWindowShouldClose(offscreen_context)) { 

     glfwSwapBuffers(offscreen_context); 
     glfwPollEvents(); 

     if (glfwGetKey(offscreen_context, GLFW_KEY_ESCAPE) == GLFW_PRESS) { 
      glfwSetWindowShouldClose(offscreen_context, GL_TRUE); 
     } 
    } 

    glfwTerminate(); 


    } 
} 
+0

我懷疑'free(texture_bytes)'是「NULL'ness」的來源:D。嘗試評論它。 – sarasvati

+1

@sarasvati是正確的,'Mat out(texture_height,texture_width,CV_8UC3,texture_bytes)'只提供數據的淺拷貝,Mat內部指向你提供的'texture_bytes',如果你刪除了內存,它就消失了。你可以做'Mat out = Mat(texture_height,texture_width,CV_8UC3,texture_bytes).clone()'來解決這個問題,更好的方法是創建一個大小正確的Mat,然後在Mat上調用'glGetTexImage'。避免複製。 – cxyzs7

+0

你在哪裏創建OpenGL上下文?沒有當前GL上下文,那些GL紋理操作都不會起作用。在[mcve]中編輯。 – genpfault

回答

0

不創建一個OpenGL上下文。簡單如此。如果沒有在當前線程上創建並激活OpenGL上下文,則所有OpenGL函數調用都是空操作。

+0

謝謝!正如你可能會告訴我對OpenGL相當新穎,所以這甚至不會發生在我身上。我現在正在閱讀。 –

+0

我試圖找到有關爲我的使用創建上下文的信息,但我發現它很難理解。我上面更新了我的代碼,以便在.cpp,.h和call部分中分開。我應該在哪裏陳述上下文,以及如何?到目前爲止,我只找到了繪製窗口的上下文的教程,這不是我想要的。 –

+0

@ T.Soemod:創建一個OpenGL上下文(不幸)是不平凡的。這就解釋了幾個應用程序框架的存在(GLUT,GLFW,SMFL,SDL)。 OpenGL總是專注於實時渲染,並將結果圖像發送到顯示器。儘管OpenGL本身是窗口系統中立,但實際創建OpenGL上下文所需的API與窗口系統(WGL,GLX,NSOpenGLView)綁定。 – datenwolf