【问题标题】:Convering OpenGL texture to OpenCV matrix将 OpenGL 纹理转换为 OpenCV 矩阵
【发布时间】:2016-08-03 00:07:03
【问题描述】:

我一直在寻找一种将 OpenGL 纹理转换为 OpenCV 矩阵类型的方法。我找到了许多指南,这些指南显示了从 OpenCV 矩阵到 OpenGL 纹理的转换,但遗憾的是相反。我还通读了this 及其answer,但这并没有让我变得更聪明。我正在用 C++ 编写并使用 OpenCV3.1 和 OpenGL4.4。

编辑:更新代码

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;

}

纹理.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();

}

标题:

#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*/

【问题讨论】:

  • 此外,您链接的答案几乎向您展示了正确的方法,您觉得其中哪一部分难以理解?
  • 没错。现在是凌晨,我的咖啡还没喝,我会更新帖子。
  • 对我来说很难看出纹理 id 的使用位置。假设我在 OpenGL 中加载图像并获取其纹理 id,如何将其转换为 OpenCV 矩阵?
  • @ThorbjørnSømod:通过返回两步,甚至在将纹理加载到 OpenGL 并将数据直接放入 OpenCV 矩阵之前。 OpenGL 不处理图像文件格式,事实上许多人实际上使用 OpenCV 来加载图像文件(OpenCV 与 OpenGL 不同,确实知道如何处理图像文件和格式)并加载生成 OpenCV 到 OpenGL 的垫子。当然,如果您想使用 OpenGL 生成图像以使用 OpenCV 处理它们,那么您必须读回图像数据,这就是 glReadPixels 的用途。但这通常涉及纹理。
  • 感谢您的意见,但这不是我想要的。基本上我所拥有的是一个系统,它将输出由纹理 ID 给出的图像。我想要的是将此图像加载到 OpenCV 中,以便我可以在那里对其执行各种操作。我不能直接将它加载到 OpenCV 中,它必须通过纹理 ID。

标签: c++ opencv opengl


【解决方案1】:

我已经测试了下面的代码,它似乎可以工作。 (注意glGetTexImage()GL_BGR的用法)。

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

【讨论】:

  • 谢谢。你刚刚拯救了我的一天!
  • @T.Soemod 很高兴听到这个消息:)。如果您的问题已解决,请考虑接受(当前)两个答案之一。
  • 我又遇到了一些麻烦。假设有适当的上下文,这就是您用于转换的所有代码吗?当我尝试显示转换后的图像时,它返回空白(白色)。
  • @T.Soemod 以下是整个源代码。 gist.github.com/anonymous/50cd7f9b51f8f550024bcaec89726494
  • 以为我只是发布并告诉您问题已解决。最后,我不得不求助于将数据写入帧缓冲区,然后从那里输出 glReadPixels()。显然,当 glGetTexImage 尝试读取它不理解的格式时,它具有输出空白数据的有效行为,并且没有已知的解决方法。非常愚蠢的恕我直言,但我想就是这样。感谢您的耐心和帮助!
【解决方案2】:
  1. 首先您需要绑定要检索的纹理,然后获取其尺寸。
  2. 找出一个连续的内存区域,将数据放入符合 OpenGL 要求的位置。
  3. 最后使用glGetTexImage获取像素。

伪代码:

GLint width,height,alignment;
glBindTexture(GL_TEXTURE_2D, textureID);
glGetIntegerv(GL_PACK_ALIGNMENT, &alignment);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
// Fiddle with alignment to make sure you get properly aligned buffer/width.
byte* imagedata = new byte[width*height*3];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, imagedata);
// move data to cv::Mat or use cv::Mat to allocate to original image buffer (imagedata)
// but be mindful that the memory region in cv::Mat is contiguous and the right
// size and all.

https://www.opengl.org/sdk/docs/man2/xhtml/glGetTexImage.xml

https://www.opengl.org/sdk/docs/man2/xhtml/glGet.xml

https://www.opengl.org/sdk/docs/man2/xhtml/glGetTexLevelParameter.xml

【讨论】:

  • 非常感谢!这与@sarasvati 的回答一起使它工作:)
  • 在@sarasvati 的帮助下,我在这方面取得了长足的进步,但是在 OpenCV 中显示 glGetTexImage() 的输出时遇到了一些问题,即函数返回时数据为空白.我有理由相信这是因为我从 glTexImage2D() 获得的纹理存在对齐问题,我尝试设置打包/解包对齐来纠正这个问题,但没有成功。你有什么指示吗?我的电话是eglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, t_width, t_height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, data);连同上面的其余代码,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 2012-06-02
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多