Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PyAPI] Tensor creation from Pillow Image #28984

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

akuporos
Copy link
Contributor

Details:

  • Tensor creation from Pillow Image

Tickets:

@akuporos akuporos requested review from a team as code owners February 13, 2025 21:19
@akuporos akuporos requested review from AlexKoff88 and artanokhov and removed request for a team February 13, 2025 21:19
@github-actions github-actions bot added category: Python API OpenVINO Python bindings category: dependency_changes Pull requests that update a dependency file labels Feb 13, 2025
@akuporos akuporos added this to the 2025.1 milestone Feb 13, 2025
@akuporos akuporos force-pushed the akup/tensor-from-pillow branch from 7031500 to 206d277 Compare February 13, 2025 21:23
@akuporos akuporos force-pushed the akup/tensor-from-pillow branch from 206d277 to 39c8c2f Compare February 13, 2025 21:32
@akuporos akuporos requested a review from Wovchena February 14, 2025 08:52
throw py::type_error("Input must be a PIL.Image.Image object");
}
auto np_array = py::module::import("numpy").attr("array")(image);
py::array array = np_array.cast<py::array>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Genai also reshapes and casts dtype: https://github.com/openvinotoolkit/openvino.genai/blob/b395127b973ac1276c8c028c9889447ebb68ed5b/samples/python/visual_language_chat/visual_language_chat.py#L39

That can be a problem because ov::Tensor doesn't allow casting. Does numpy preserve Image's layout and dtype? I see the test verifies that, but the used shape and dtype are kind of mainstream, so that doesn't explain what happens to uncommon shapes and types.

@popovaan, do you remember why reshape() and astype() are there?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reshape() is needed here, because pic.getdata() returns flattened data. For example for 100x200x3 image pic.getdata() will have shape 20000x3.
astype(np.uint8) is needed because pic.getdata() contains int64 values and if we remove the cast, we get error from genai:
RuntimeError: Exception from src/core/src/runtime/tensor.cpp:96:
Exception from src/inference/src/dev/make_tensor.cpp:66:
Tensor data with element type i64, is not representable as pointer to u8

Copy link
Contributor

@popovaan popovaan Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked np.array(pic) works fine and preserves shapes and type. I don't remember why I used pic.getdata(), looks like we can replace it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ilya-lavrenov, if image reading can be reduced to ov.Tensor(np.array(Image.open(path).convert("RGB"))), is Tensor creation from Pillow Image is still needed? I'd not add it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ilya-lavrenov, if image reading can be reduced to ov.Tensor(np.array(Image.open(path).convert("RGB"))), is Tensor creation from Pillow Image is still needed? I'd not add it.

up to PR authors.

ov.Tensor(np.array(Image.open(path).convert("RGB")))

People need to know about this np.array..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion for pure user convenience we could have this binding. Constructing a Tensor from PIL image out of the box is more user friendly than a oneliner, in which the image has to be opened, converted to RGB and then cast to np.array - the user has to know/remember about all of these.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This binding doesn't remove the need to know about opening and conversion to RGB.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still, the way I see it is this PR allows users to omit the np.array casting and makes Python API more convenient and working out of the box, which I think aligns with Python values as a language. I agree it's rather a minor change and we could do without it, but out of the two options, I think it's a change for the better. IMO this PR should be merged.

@akuporos akuporos requested review from a team as code owners February 18, 2025 22:04
@akuporos akuporos requested review from itikhono and removed request for a team February 18, 2025 22:04
@github-actions github-actions bot added category: Core OpenVINO Core (aka ngraph) category: CPU OpenVINO CPU plugin category: transformations OpenVINO Runtime library - Transformations category: ONNX FE OpenVINO ONNX FrontEnd labels Feb 18, 2025
@github-actions github-actions bot added category: extensions OpenVINO Extensibility Mechanism for custom operations category: CPP API OpenVINO CPP API bindings labels Feb 18, 2025
@mlukasze mlukasze requested a review from popovaan February 19, 2025 05:57
Copy link
Contributor

@t-jankowski t-jankowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok for core part (looks like only code style fixes)

@github-actions github-actions bot removed category: Core OpenVINO Core (aka ngraph) category: CPU OpenVINO CPU plugin category: transformations OpenVINO Runtime library - Transformations category: ONNX FE OpenVINO ONNX FrontEnd category: extensions OpenVINO Extensibility Mechanism for custom operations category: CPP API OpenVINO CPP API bindings labels Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category: dependency_changes Pull requests that update a dependency file category: Python API OpenVINO Python bindings
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants