Skip to content

Commit 95ac593

Browse files
committed
add new file in gallery
1 parent 672fd6d commit 95ac593

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""
2+
=======================================
3+
Converting between tensor and PIL image
4+
=======================================
5+
6+
.. note::
7+
Try on `collab <https://colab.research.google.com/github/pytorch/vision/blob/gh-pages/main/_generated_ipynb_notebooks/plot_custom_tv_tensors.ipynb>`_
8+
or :ref:`go to the end <sphx_glr_download_auto_examples_transforms_plot_custom_tv_tensors.py>` to download the full example code.
9+
10+
In thie example, we explain the basic usgae of :func:`~torchvision.transforms.functional.to_tensor`, :func:`~torchvision.transforms.functional.pil_to_tensor` and :func:`~torchvision.transforms.functional.to_pil_image`.
11+
And the difference between :func:`~torchvision.transforms.functional.to_tensor` and :func:`~torchvision.transforms.functional.pil_to_tensor`.
12+
"""
13+
14+
# %%
15+
# torchvision.transforms.functional.to_tensor
16+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17+
# In this cell, we illustrate the different representation of a PIL image and tensor
18+
import PIL.Image as Image
19+
from torchvision.transforms.functional import to_tensor
20+
from helpers import plot # use your favorite visualization library
21+
22+
img_pil = Image.open('../assets/person1.jpg')
23+
width, height = img_pil.size
24+
# There is no straight forward way to get channel information
25+
# Please read https://pillow.readthedocs.io/en/stable/handbook/concepts.html for more detail
26+
num_channels = 3 # hardcoded since it's a color image.
27+
print("PIL image: width x height x num_channels:", width, height, num_channels)
28+
29+
img_tensor = to_tensor(img_pil)
30+
num_channels, height, width = img_tensor.shape
31+
print("Tensor image: num_channels x height x width:", num_channels, height, width)
32+
plot([img_tensor])
33+
34+
# %%
35+
# torchvision.transforms.functional.pil_to_tensor
36+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37+
# In this cell, we explain the difference between :func:`~torchvision.transforms.functional.pil_to_tensor` vs. :func:`~torchvision.transforms.functional.to_tensor`
38+
from torchvision.transforms.functional import pil_to_tensor
39+
40+
img_pil = Image.open('../assets/person1.jpg')
41+
img_to_tensor = to_tensor(img_pil)
42+
num_channels, height, width = img_to_tensor.shape
43+
print("Tensor image(to_tensor): num_channels x height x width:", num_channels, height, width)
44+
print("Tensor image(to_tensor) datatype:", img_to_tensor.dtype)
45+
img_pil_to_tensor = pil_to_tensor(img_pil)
46+
num_channels, height, width = img_pil_to_tensor.shape
47+
print("Tensor image(pil_to_tensor): num_channels x height x width:", num_channels, height, width)
48+
print("Tensor image(pil_to_tensor) datatype:", img_pil_to_tensor.dtype)
49+
plot([img_to_tensor, img_pil_to_tensor])
50+
51+
# %%
52+
# The shape is the same but **data type** is different! The **tensor value** is also different!
53+
54+
# %%
55+
print(img_to_tensor) # tensor that is returned by calling to_tensor()
56+
print(img_pil_to_tensor) # tensor that is returned by calling pil_to_tensor()
57+
58+
# %%
59+
# Notice :func:`~torchvision.transforms.functional.to_tensor` automatically scale the image, but :func:`~torchvision.transforms.functional.pil_to_tensor` does not. To rescale the image back,
60+
61+
import torch
62+
img_pil_to_tensor_2 = (img_to_tensor * 255).to(torch.uint8)
63+
print((img_pil_to_tensor_2 == img_pil_to_tensor).all().item()) # check if two tensors are same
64+
65+
# %%
66+
# **TLDR** it's recommended to use :func:`~torchvision.transforms.functional.pil_to_tensor` for visualization tasks since most visualization library
67+
# expects input image to be ``torch.uint8``. On the other hand, :func:`~torchvision.transforms.functional.to_tensor` is better for computation tasks since models, optimizers and loss functions expect
68+
# input image to be ``torch.float32``.
69+
70+
71+
# %%
72+
# torchvision.transforms.functional.to_pil_image
73+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74+
# In this cell, we explain an example usage of :func:`~torchvision.transforms.functional.to_pil_image`
75+
from torchvision.transforms.functional import to_pil_image
76+
77+
img_pil = Image.open('../assets/person1.jpg')
78+
79+
# convert to tensor using to_tensor() and pil_to_tensor()
80+
img_to_tensor = to_tensor(img_pil)
81+
img_pil_to_tensor = pil_to_tensor(img_pil)
82+
83+
# convert back to PIL image from tensor
84+
pil_img_to_tensor = to_pil_image(img_to_tensor)
85+
pil_img_pil_to_tensor = to_pil_image(img_pil_to_tensor)
86+
print(pil_img_to_tensor)
87+
print(pil_img_pil_to_tensor)
88+
89+
# %%
90+
# Both tensor can be converted back to PIL image.
91+

0 commit comments

Comments
 (0)