首先我们创建一个空的(或未初始化的)cv::Mat
以便直接读取我们的数据。这可以在启动时完成一次,但另一方面cv::Mat::create
当图像已经具有匹配的尺寸和类型时,实际上并不会花费太多。类型取决于您的需求,通常是这样的CV_8UC3
对于 24 位彩色图像。
cv::Mat img(height, width, CV_8UC3);
or
img.create(height, width, CV_8UC3);
那么你必须考虑到cv::Mat
不一定存储连续的图像行。每行末尾可能有一个小的填充值,以使行 4 字节对齐(或 8 字节?)。所以你需要搞乱像素存储模式:
//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
将会:
glReadPixels(0, 0, img.cols, img.rows, GL_BGR, GL_UNSIGNED_BYTE, img.data);
最后,OpenCV从上到下存储图像。因此,您可能需要在获取它们后翻转它们,或者首先在 OpenGL 中渲染它们翻转(这可以通过调整投影矩阵来完成,但在这种情况下请注意三角形方向)。翻转一个cv::Mat
垂直,你可以使用cv::flip http://opencv.willowgarage.com/documentation/cpp/core_operations_on_arrays.html#cv-flip:
cv::flip(img, flipped, 0);
所以要记住 OpenCV:
- 从上到下、从左到右存储图像
- 按 BGR 顺序存储彩色图像
- 可能不会存储紧密排列的图像行