OpenCV + OpenGL - 将OpenGL图像作为OpenCV摄像头获取

时间:2013-10-23 23:15:42

标签: c++ opengl opencv

我想获取OpenGL图像并将其提供给OpenCV进行分析(作为OpenCV算法的模拟器),但我找不到有关它的更多信息,我只能找到相反的方法(放置OpenCV) OpenGL中的图像)。有人可以解释怎么做吗?

编辑:

我将模拟机器人顶部的摄像头,因此我将实时渲染3D环境并将其显示在用户的Qt GUI中。我将为用户提供使用真实网络摄像头馈送或模拟3D场景(随着机器人移动而改变)的选项,并且OpenCV算法对于两个输入都是相同的,因此用户可以测试他的代码而无需使用真实的机器人一直都在。

3 个答案:

答案 0 :(得分:3)

您可能正在寻找功能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不是一种非常有效的方法,这里有一些示例代码使用Framebuffers和Pixel Buffer Objects来有效地传输: How to render offscreen on OpenGL?

答案 1 :(得分:2)

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

你要做的基本上是:

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

如另一个答案所示,阅读OpenGL纹理只需调用glRead()函数即可。 你得到的通常是3或4个通道,每个数据8位(RGB / RGBA - 每通道8位),但它可能取决于你的实际OpenGL背景。

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

答案 2 :(得分:1)

我的研究需要这个。 我接受了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;
}

我希望有人觉得这很有用。