OpenCV Mat to OpenGL - glBindTexture()出错

时间:2018-02-23 12:11:40

标签: c++ opencv opengl

我正在尝试将OpenCV cv::Mat图像转换为OpenGL纹理(我需要一个指向纹理的GLuint)。这是我到目前为止的代码,拼凑在众多Google搜索中:

void otherFunction(cv::Mat tex_img) // tex_img is a loaded image
{
    GLuint* texID;
    cvMatToGlTex(tex_img, texID);

    // Operations on the texture here 
}

void cvMatToGlTex(cv::Mat tex_img, GLuint* texID) 
{
    glGenTextures(1, texID);
    // Crashes on the next line:
    glBindTexture(GL_TEXTURE_2D, *texID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img.cols, tex_img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, tex_img.ptr());

    return;
}

调用glBindTextures时会发生崩溃。

我尝试了catch (const std::exception& ex)catch (...)的所有异常的try-catch,但它似乎没有抛出任何东西,只是让我的程序崩溃。

如果我正在做任何明显错误的事情,我道歉,这是我第一次使用OpenGL,而且对于我来说,使用C ++还是处于早期阶段。从昨天开始我一直坚持这个。我对OpenGL纹理有一个基本的误解吗?如有必要,我愿意对代码进行重大修改。我正在运行Ubuntu 16.04,如果它改变了什么。

1 个答案:

答案 0 :(得分:2)

好的,这就是发生的事情:

void otherFunction(cv::Mat tex_img)
{
    GLuint* texID; // You've created a pointer but not initialised it. It could be pointing
                   // to anywhere in memory.
    cvMatToGlTex(tex_img, texID); // You pass in the value of the GLuint*
}

void cvMatToGlTex(cv::Mat tex_img, GLuint* texID) 
{
    glGenTextures(1, texID); // OpenGL will dereference the pointer and write the
                // value of the new texture ID here. The pointer value you passed in is 
                // indeterminate because you didn't assign it to anything. 
                // Dereferencing a pointer pointing to memory that you don't own is 
                // undefined behaviour. The reason it's not crashing here is because I'll 
                // bet your compiler initialised the pointer value to null, and 
                // glGenTextures() checks if it's null before writing to it. 

    glBindTexture(GL_TEXTURE_2D, *texID); // Here you dereference an invalid pointer yourself. 
                            // It has a random value, probably null, and that's 
                            // why you get a crash

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

    return;
}

解决此问题的一种方法是将指针分配给GLuint,如:

GLuint* texID = new GLuint; // And pass it in

这对初学者有用,但你应该小心你如何解决这个问题。任何分配了新内容的东西都必须通过调用删除来删除,否则你将泄漏内存。智能指针一旦超出范围就会自动删除它。

你也可以这样做:

GLuint texID;
cvMatToGlTex(tex_img, &texID);

请记住,虽然GLuint texID的生命周期只在你声明它的那个函数中,因为它是一个局部变量。我不确定有什么更好的方法可以做到这一点,因为我不知道你的程序是什么样的,但至少应该让崩溃消失。