使用 openCV 导出 openGL 纹理时出现异常

anomaly while exporting openGL texture using openCV

出于调试目的,我决定编写纹理导出函数:

def image_export(self, file_name: str):
    im_format = file_name.rsplit('.')[-1]
    if im_format in ('jpg',):
        iformat = gl.GL_BGR
    elif im_format in ('png',):
        iformat = gl.GL_BGRA
    else:
        raise NotImplementedError

    with self: # binding texture
        # gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
        im = (gl.glGetTexImage(gl.GL_TEXTURE_2D, 0, iformat, gl.GL_FLOAT) * 255).astype('uint8')

    im = np.flip(im, axis=0)
    cv2.imwrite(file_name, im)

使用 500x500 纹理进行测试并且工作正常:

但是当我尝试 500x600 时,事情变得很奇怪:

我必须重塑它以获得所需的图像:

    # ...
    im = im.reshape((600, 500, 3)) # added line
    im = np.flip(im, axis=0)
    cv2.imwrite(file_name, im)

然后结果是:

最近我问了一个问题 所以我尝试了 gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1),但没有发现它有任何影响。 重塑没有意义。如果不重塑,我应该简单地获得 90 度旋转的图像。我有什么不明白的?



添加:
看完评论,试着总结一下我的理解。你(某人)能证实我的结论吗?

reshape is not the same as transposereshape 不会改变轴(因此不会旋转)但会改变数组的形状(宽度和高度)。

例如:

a = numpy.array([[1, 2, 3, 4],
                 [5, 6, 7, 8]])
ar = a.reshape((4, 2))
print(ar)

重塑:

[[1 2]
 [3 4]
 [5 6]
 [7 8]]

转置:

at = a.transpose((1, 0))
print(at)
[[1 5]
 [2 6]
 [3 7]
 [4 8]]

glGetTexImage returns 具有形状的数组 (width, height, 频道)。这意味着 RGB 200x100 图像的形状是 (200, 100, 3)。您可以使用 print(im.shape).

来验证这一点

然而 numpy.ndarray.shape is specified in row major order (rows, columns). This means the shape of the numpy.array

a = np.array([[1, 2, 3, 4],
             [5, 6, 7, 8]])

不是 (4, 2) 而是 (2, 4).

表示 RGB 4x2 图像的数组的形状

a = np.array(
   [[(r1, g1, b1), (r2, g2, b2), (r3, g3, b3), (r4, g4, b4)],
    [(r5, g5, b5), (r6, g6, b6), (r7, g7, b7), (r8, g8, b8)]])

是 (2, 4, 3).

PyOpenGL 和 NumPy (cv2) 对形状的解释不同。因此,您必须更改形状和 reshape 数组:

im = im.reshape((im.shape[1], im.shape[0], im.shape[2]))

总结:没有什么复杂的。 PyOpenGL returns 形式的形状信息 (w, h, c),但 NumPy 需要 (h, w, c)。图像的像素是线性存储的。不需要更改顺序,但必须更改它们的解释方式。