本文介绍了将数据从glReadPixels()转换为OpenCV :: Mat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从 glReadPixels()的动画中获取每个OpenGL帧,并将数据转换为 OpenCV :: Mat 。我知道 glReadPixels()按照从下到上的顺序从左到右获取数据。另一方面,OpenCV以不同的方式存储数据。

I want to get every OpenGL frame from an animation with glReadPixels() and convert the data to OpenCV::Mat. I know that glReadPixels() gets the data by rows from the lower one to upper one, from left to right. On the other hand, OpenCV stores the data differently.

有人知道任何库或任何教程/示例,帮助我从 glReadPixels 到C ++中的 OpenCV:Mat

Does anybody know any library or any tutorial/example that helps me to convert data from glReadPixels to a OpenCV:Mat in C++?

总结 b

 OpenGL frame      ----------------------->        CV::Mat

Data from left to right,                    Data from left to right,
bottom to top.                              top to bottom.


推荐答案

首先我们创建一个空c $ c> cv :: Mat ,以便我们的数据直接读入。这可以在启动时执行一次,但另一方面 cv :: Mat :: create 在图像已经具有匹配的大小和类型时并不会花费太多。类型取决于您的需要,通常它是类似于 CV_8UC3 的24位彩色图像。

First we create an empty (or unititialized) cv::Mat for our data to be read into directly. This can be done once at startup, but on the other hand cv::Mat::create doesn't really cost much when the image already has matching size and type. The type depends on your needs, usually it's something like CV_8UC3 for a 24-bit color image.

cv::Mat img(height, width, CV_8UC3);

img.create(height, width, CV_8UC3);

然后你必须考虑 cv :: Mat 不连续地存储图像行。在每行的末尾可能有一个小的填充值,使行4字节对齐(或8?)。所以你需要混乱像素存储模式:

Then you have to account for cv::Mat not neccessarily storing image rows contiguously. There might be a small padding value at the end of each row to make rows 4-byte aligned (or 8?). So you need to mess with the pixel storage modes:

//use fast 4-byte alignment (default anyway) if possible
glPixelStorei(GL_PACK_ALIGNMENT, (img.step & 3) ? 1 : 4);

//set length of one complete row in destination data (doesn't need to equal img.cols)
glPixelStorei(GL_PACK_ROW_LENGTH, img.step/img.elemSize());

接下来,矩阵的类型会影响 glReadPixels的格式和类型参数。如果你想要彩色图像,你必须记住,OpenCV通常以BGR顺序存储颜色值,所以你需要使用 GL_BGR(A)(这是添加了OpenGL 1.2 )而不是 GL_RGB(A)。对于一个组件图像,使用 GL_LUMINANCE (其合计单个颜色分量)或 GL_RED GL_GREEN ,...(获取单个组件)。因此,对于我们的 CV_8UC3 映像,将其直接读入 cv :: Mat 的最终调用将是:

Next, the type of the matrix influences the format and type parameters of glReadPixels. If you want color images you have to keep in mind that OpenCV usually stores color values in BGR order, so you need to use GL_BGR(A) (which were added with OpenGL 1.2) instead of GL_RGB(A). For one component images use either GL_LUMINANCE (which sums the individual color components) or GL_RED, GL_GREEN, ... (to get an individual component). So for our CV_8UC3 image the final call to read it directly into the cv::Mat would be:

glReadPixels(0, 0, img.cols, img.rows, GL_BGR, GL_UNSIGNED_BYTE, img.data);

最后,OpenCV从上到下存储图像。所以你可能需要在获得它们之后翻转它们,或者在OpenGL中渲染它们(在这种情况下可以通过调整投影矩阵,但要注意三角形的方向)。要垂直翻转 cv :: Mat ,您可以使用

Finally, OpenCV stores images from top to bottom. So you may need to either flip them after getting them or render them flipped in OpenGL in the first place (this can be done by adjusting the projection matrix, but keep an eye on triangle orientation in this case). To flip a cv::Mat vertically, you can use cv::flip:

cv::flip(img, flipped, 0);

因此,为了记住OpenCV:

So to keep in mind OpenCV:

这篇关于将数据从glReadPixels()转换为OpenCV :: Mat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!