1

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

编辑:

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

4

3 回答 3

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 并不是一种非常有效的方法,因此这里有一些使用帧缓冲区和像素缓冲区对象来有效传输的示例代码: 如何在 OpenGL 上渲染屏幕外?

于 2013-10-24T12:22:22.427 回答
2

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

你要做的基本上是:

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

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

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

于 2013-10-24T09:29:07.170 回答
2

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

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

于 2015-05-23T11:17:56.293 回答