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

zfciruhq  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(134)

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

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度旋转的图像。我不明白什么?
增加:
阅读完评论后,试图总结我的理解。你(有人)能验证我的结论吗?

p8ekf7hl

p8ekf7hl1#

reshapetranspose不同。reshape不会变更轴(因此不会旋转),但会变更数组的形体(长度和高度)。
例如:
第一个
整形:

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

转置:
第一个
glGetTexImage返回一个形状为(widthheightchannels)的数组。这意味着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)。图像的像素是线性存储的。顺序不需要改变,但它们的解释方式必须改变。

相关问题