【问题标题】:Using glGetTexImage() to aquire OpenCV Mat使用 glGetTexImage() 获取 OpenCV Mat
【发布时间】:2016-12-10 17:46:29
【问题描述】:

我正在尝试使用来自 OpenGL 的 glGetTexImage() 的输出来制作 OpenCV Mat()。我试图从中获取信息的纹理是使用调用制作的;

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8UI, iWidth, iHeight, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pImageData);

所以我尝试使用;

    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);

    Matrix = Mat(texture_height, texture_width, CV_8UC3, texture_bytes);

我想知道的是,如果有人知道我应该将 glGetTexImage() 的格式和类型设置为什么以使其正常工作。另外,我应该将 Mat() 的类型设置为什么?

您可以假设上下文设置正确,并且输入的纹理是正确的。我已经通过使用 OpenGL 在屏幕上显示纹理来验证这一点。提前致谢!

【问题讨论】:

  • 您目前的尝试究竟有什么问题?你根本没有得到任何数据吗?或者看起来不正确的数据?尝试调用 glGetError() 以防万一,即使这些参数对我来说看起来有效。
  • 当我尝试从给定纹理中获取 texture_bytes 数据时,出现了我的问题。 texture_bytes 返回空白(如“ffffffffffffffffff”)。所以是的,我根本没有得到任何数据。我很肯定数据在那里,因为纹理在 OpenGL 中渲染和显示效果很好,但它只会在 OpenCV 中给我一个灰屏。我希望这能稍微澄清一下这个问题:)
  • 更正,我似乎从纹理数据中获得的唯一数据是“ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ”。

标签: c++ opencv opengl


【解决方案1】:

glGetTexImage() 调用使用的 format 参数与纹理的内部格式不匹配:

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8UI, iWidth, iHeight, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, pImageData);
...
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGR, GL_UNSIGNED_BYTE, texture_bytes);

对于在这种情况下拥有的整数纹理,您需要对glGetTexImage() 使用适用于整数纹理的 format 参数。在您的示例中,这将是:

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

如果您在获取所需的 OpenGL 行为时遇到任何问题,最好致电glGetError()。在这种情况下,您将收到 GL_INVALID_OPERATION 错误,基于规范中的此错误条件:

format 是表 8.3 中的整数格式之一,纹理图像的内部格式不是整数,或者 format 不是表 8.3 中的整数格式之一,内部格式是整数。

【讨论】:

    【解决方案2】:

    我最近遇到了从OpenGL获取数据到OpenCV的问题。不过我没有使用glGetTexImage

    我所做的是在帧缓冲区中进行屏幕外渲染,其纹理初始化如下:

    GLuint texture;
    if (glIsTexture(texture)) {
        glDeleteTextures(1, &texture);
    }
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    

    然后在我的draw call之后,我使用glReadPixels获取数据:

    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    
    cv::Mat texture = cv::Mat::zeros(height, width, CV_32FC3);
    glReadPixels(0, 0, width, height, GL_BGR, GL_FLOAT, texture.data);
    

    希望对你有帮助。

    【讨论】:

    • 嗯,我真的希望不必通过帧缓冲区,因为我只使用 OpenGL 作为 OpenCV 的端口,但如果没有其他问题,也许我会试试你的版本。谢谢!
    猜你喜欢
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多