Best way to integrate numpy?

OK, so I have images as numpy arrays (obtained different ways, sometimes from PIL).

How to display an image given its numpy array, i.e. as rgb? How to create PNMImage from numpy array, how to create texture, how to render it?

Question is also about the opposite direction: how to obtain RGB numpy array from texture/PNMImage?

I don’t know the best way, but read through the following two threads, which likewise deal with converting a numpy array into a Panda image.

In those cases, the image is converted into a texture–but a texture can be used to generate a PNMImage, I believe.

https://discourse.panda3d.org/t/starting-out-looking-for-tips-for-showing-binocular-images-from-numpy-arrays-plus-an-error

https://discourse.panda3d.org/t/small-issue-with-using-numpy-arrays-as-textures/

1 Like

Personally, I tend to use OpenCV to do this kind of thing. Whether or not it’s the “best” way I’m not sure. Example:

img_array = Image.frombuffer('RGBA',(base.buff_hw[0], base.buff_hw[1]),img.get_ram_image_as('RGBA'),'raw','RGBA',-1,-1)
cv_img = cv2.cvtColor(numpy.array(img_array), cv2.COLOR_RGBA2BGR)
frame_r = cv2.resize(cv_img, (base.buff_hw[0], base.buff_hw[1]), interpolation=cv2.INTER_CUBIC)

How do you apply the resulting image to Panda scene?

You can get a texture “as data” with tex.get_ram_image() (which returns an object that you can construct a memoryview() from) and set it with tex.set_ram_image(data).

The order is BGRA, so if you want to get it as a different component ordering you can use tex.get_ram_image_as("RGBA"), same for set_ram_image_as, though it’ll be a bit less efficient.

This is the best way to get textures between numpy/PIL and Panda3D.

The simplest way might be to apply it as a texture to a quad/card.

Something like this:

# Presume that you've converted your numpy array into a texture,
# and stored that texture in a variable called 'myTex"

from panda3d.core import CardMaker

cardMaker = CardMaker("card maker")

card = cardMaker.generate()

card.setTexture(myTex)

card.reparentTo(render)

# Note: Don't forget to place the camera or card such that
# the camera can see the card!