【问题标题】:anomaly while exporting openGL texture using openCV使用openCV导出openGL纹理时出现异常
【发布时间】:2021-05-28 23:28:54
【问题描述】:

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

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)

然后导致:

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



补充:
阅读评论后,试图总结我的理解。你(某人)能验证我的结论吗?

【问题讨论】:

  • 我没有发表评论,而是完整的回答。这没有什么复杂的。 PyOpenGL 以 (w, h, c) 的形式返回形状信息,但 NumPy 需要 (h, w, c)。图像的像素是线性存储的。顺序不需要改变,但它们的解释方式必须改变。
  • 我认为您的第一条评论说明了我在最后一张图片的右下角评论中所说的“...(数组)像素索引不代表其在纹理中的位置”,对吗?但如果是这样,这就留下了实现这样做的原因。它可以简单地将数组索引与纹理像素坐标匹配。

标签: python numpy opencv opengl cv2


【解决方案1】:

reshapetranspose 不同。 reshape 不会改变轴(因此不会旋转),但会改变数组的形状(宽度和高度)。

例如:

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 返回一个形状为 (width, height, channels) 的数组。这意味着 RGB 200x100 图像的形状是 (200, 100, 3)。您可以通过print(im.shape) 验证这一点。

但是numpy.ndarray.shape 是按行主要顺序指定的()。这意味着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 以 (w, h, c) 的形式返回形状信息,但 NumPy 需要 (h, w, c)。图像的像素是线性存储的。顺序不需要改变,但是它们的解释方式必须改变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    相关资源
    最近更新 更多