Issue
For debugging purpose I decided to write texture exporting function:
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)
Tested with 500x500 texture and works fine:
But when I try 500x600 thing goes strange:
I have to reshape it to get desired image:
# ...
im = im.reshape((600, 500, 3)) # added line
im = np.flip(im, axis=0)
cv2.imwrite(file_name, im)
Recently I've asked question glTexImage2D data not filled as expected
so I tried gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
, but didnt found it effecting anything.
Reshaping doesn't make sense. Without reshaping, I should simply get 90 degree rotated image. What am I not understanding?
ADDITION:
After reading the comment, tried to summarize my understanding. Can you(someone) verify my conclusion?
Solution
reshape
is not the same as transpose
. reshape
does not change the axis (and thus not rotate) but it changes the shape (width and height) of the array.
e.g.:
a = numpy.array([[1, 2, 3, 4],
[5, 6, 7, 8]])
ar = a.reshape((4, 2))
print(ar)
reshape:
[[1 2] [3 4] [5 6] [7 8]]
transpose:
at = a.transpose((1, 0))
print(at)
[[1 5] [2 6] [3 7] [4 8]]
glGetTexImage
returns an array with the shape (width, height, channels). This means the shape of an RGB 200x100 image is (200, 100, 3). You can verify this with print(im.shape)
.
However the 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]])
is not (4, 2) but (2, 4).
The shape of an array that represents a RGB 4x2 image
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)]])
is (2, 4, 3).
PyOpenGL and NumPy (cv2) interpret the shape differently. Therefore you must change the shape and reshape
the array:
im = im.reshape((im.shape[1], im.shape[0], im.shape[2]))
Summarize: There is nothing complicated about that. PyOpenGL returns shape information in the form (w, h, c), but NumPy expects (h, w, c). The pixels of the image are stored linearly. The order does not need to be changed, but how they are interpreted must be changed.
Answered By - Rabbid76
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.