2013-10-23 64 views
0

我想获取一个OpenGL图像并将其提供给OpenCV进行分析(作为OpenCV算法的模拟器),但我没有找到关于它的很多信息,我只能找到是另一种方式(在OpenGL中放置一个OpenCV图像)。有人可以解释如何做?OpenCV + OpenGL - 获取OpenGL图像作为OpenCV摄像机

编辑:

我将模拟上的机器人的顶部上的照相机,所以我将在实时3D环境渲染和在一个Qt GUI显示它给用户。我会让用户选择使用一个真实的摄像头反馈或一个模拟的3D场景(随着机器人移动而改变),并且OpenCV算法对于两个输入都是相同的,因此用户可以测试他的代码而不必使用真实的机器人始终。

+1

“OpenGL图像”在这种情况下意味着什么?纹理?一个场景呈现给framebuffer?一个场景呈现给一些离屏缓冲区? –

+0

@MatsPetersson我用更多的解释更新了这个问题 – mFeinstein

+0

@MatsPetersson我猜它是“一个渲染到framebuffer的场景”选项,要更清楚。我还在深入学习OpenGL,所以我试图找到更多关于所有必读内容的信息,而且我找不到太多的东西......任何方向都是最受欢迎的! – mFeinstein

回答

2

您可能正在寻找功能glReadPixels。它将下载OpenGL当前显示的任何内容到缓冲区。

unsigned char* buffer = new unsigned char[width*height*3]; 
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
cv::Mat image(height, width, CV_8UC3, buffer); 
cv::imshow("Show Image", image); 

对于OpenCV的你可能还需要翻转并转换为BGR为好。

编辑:由于只使用glReadPixels是不是一个非常有效的方式做到这一点,这里是使用帧缓存和像素缓冲对象有效地传送一些示例代码: How to render offscreen on OpenGL?

+0

我是OpenCV的新手,是BGR特定的东西还是只是RGB向后? – mFeinstein

+1

只需要注意,glReadPixels是使300美元的图形卡产生5fps的极好方式,因为每次调用glReadPixels时,图形芯片都将不得不消耗整个工作流程。如果你听说过CPU中的“branch mispredicts”,这是同样的事情,但是10000倍差。 –

+0

@MatsPetersson该死的,它看起来像一个干净的解决方案...你有任何bettert选项,也许我可以搜索一些代码? – mFeinstein

2

我在之前的研究项目中做过。这里没有太多困难。

,你所要做的主要是:

  • 使从OpenGL的读一些预分配内存缓冲区纹理;
  • 应用一些几何变换(翻转X和/或Y坐标)来说明OpenGL和OpenCV之间可能不同的坐标系。这是一个细节,但它有助于可视化(提示:使用内含F字母的纹理快速找到需要翻转的坐标!);
  • 您可以直接在预分配的内存缓冲区周围构建OpenCV对象,然后直接对其进行处理或将其复制到其他矩阵对象并对其进行处理。

正如在另一个答案中指出的,读取OpenGL纹理是调用glRead()函数的一个简单问题。 你得到的通常是3或4个通道,每个数据8位(RGB/RGBA - 每通道8位),尽管它可能取决于你实际的OpenGL上下文。

如果颜色对您很重要,您可能需要(但不是必需的)将RGB图像数据转换为BGR格式(蓝 - 绿 - 红)。由于历史原因,这是OpenCV中默认的颜色通道排序。 例如,您可以通过致电cv::cvtColor(source, dest, cv::COLOR_RGB2BGR)来完成此操作。

+0

我会尝试一下,看看它是怎么回事,谢谢! – mFeinstein

0

我需要为我的研究。 我接受了littleimp的建议,但修复颜色和翻转图像花费宝贵的时间来弄清楚。

这就是我最终的结果。

typedef Mat Image ; 

typedef struct { 
    int width; 
    int height; 
    char* title; 
    float field_of_view_angle; 
    float z_near; 
    float z_far; 
} glutWindow; 

glutWindow win; 

Image glutTakeCVImage() { 
    // take a picture within glut and return formatted 
    // for use in openCV 
    int width = win.width; 
    int height = win.height; 
    unsigned char* buffer = new unsigned char[width*height*3]; 
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
    Image img(height, width, CV_8UC3, buffer); 
    Image flipped_img; 
    flip(img,flipped_img,0); 
    Image BGR_img; 
    cvtColor(flipped_img,BGR_img, COLOR_RGB2BGR); 
    return BGR_img; 
} 

我希望有人认为这有用。