fury-gl / fury

FURY - Free Unified Rendering in pYthon.
https://fury.gl
Other
230 stars 163 forks source link

Fury should warn when image data being sent to it is not of form np.array(dtype=np.uint8) #733

Open RelativisticMechanic opened 1 year ago

RelativisticMechanic commented 1 year ago

This is a small issue, but it did cost me some time. I manually tried to flip an image horizontally by creating a separate numpy array.


import numpy as np
from fury import window, actor, io

scene = window.Scene()

image = io.load_image("world-map.png")
h = image.shape[0]
w = image.shape[1]
new_image = np.zeros(shape=image.shape)

for i in range(h):
    for j in range(w):
        # Horizontal flip
        new_image[i, j] = image[i, w - j - 1]

scene.add(actor.texture_on_sphere(new_image))
window.show(scene, size=(600, 600), reset_camera=False)

Ok! So here' what I got:

image

This baffled me for quite a while. After a few minutes of debugging, I tried:

io.save_image(new_image, "worldmap-flipped.png")

And PIL caught the problem:


File "C:\Users\sgaut\PycharmProjects\MDAnalysisTest\venv\lib\site-packages\PIL\Image.py", line 3083, in fromarray
    raise TypeError(msg) from e
TypeError: Cannot handle this data type: (1, 1, 4), <f8

By default, at least on my system, np.array chooses to use 64-bit floating point numbers which seems to be an issue. Thus, changing this line,


new_image = np.zeros(shape=image.shape)

to


new_image = np.zeros(shape=image.shape, dtype=np.uint8)

Fixes the issue and gives the desired result.

image

It's a very small issue but I do think Fury should either give a warning or error out like PIL did when dealing with something like this. Could've saved me half an hour. I'll try to go through the source and work a PR, or someone else can also do it before me.

Thanks!

jalajk24 commented 1 year ago

Can I work on this issue? I found it interesting to contribute

Jash-Shah commented 1 year ago

Hi, this issue could be solved by adding dtype checks to all the texture functions in the actor.py file that only accept rgb image data of type np.uint8. Specifically adding the following exception raising to the texture(), texture_2d(), texture_on_sphere() and texture_update() functions:

if rgb.dtype != np.uint8:
        raise TypeError(f'Can only handle images of type: np.uint8. DType of the given rgb image is {rgb.dtype}')
marinicadenisandrei commented 1 year ago

Hi, I want to be part of this organization Google Summer of Code GSOC 2023! Can you tell me some details about what I should do to be accepted, I would really like to take part in this program and be able to learn as many things as possible. I made a code for this problem, you can take a look.

import numpy as np from fury import window, actor, io

def check_image_data(image): if not isinstance(image, np.ndarray): raise TypeError("Image data must be a numpy array.") if image.dtype != np.uint8: raise TypeError("Image data must be of type np.uint8.")

def flip_image_horizontally(image): h, w = image.shape[:2] new_image = np.zeros(shape=image.shape, dtype=np.uint8) for i in range(h): for j in range(w): new_image[i, j] = image[i, w - j - 1] return new_image

image = io.load_image("world-map.png") check_image_data(image) new_image = flip_image_horizontally(image)

scene = window.Scene() scene.add(actor.texture_on_sphere(new_image)) window.show(scene, size=(600, 600), reset_camera=False)