ToPILImage in PyTorch (1)
Buy Me a Coffee☕ *Memos: My post explains how to convert and scale a PIL Image to an Image in PyTorch. My post explains Compose(). My post explains ToImage(). My post explains ToDtype(). My post explains ToTensor(). My post explains PILToTensor(). My post explains OxfordIIITPet(). ToPILImage() can convert an Image([..., C, H, W]), tensor or ndarray to a PIL(Pillow library) Image([H, W, C]) and doesn't scale its values to [0.0, 1.0] as shown below: *Memos: The 1st argument for initialization is mode(Optional-Default:None-Type:PIL.Image mode): *Memos: If it's None, a mode is automatically set depending on img. For the 1 channel(int) of 2D or 3D, e.g. [[0, 1, 2, 3]], [[[0]]], etc, 'I' is used. For the 1 channel(float) of 2D or 3D, e.g. [[0], [1], [2], [3]], [[[0.]]], etc, 'L' is used. For the 2 channels(int/float) of 3D, e.g. [[[0], [[1]]], [[[0.], [[1.]]], etc, 'LA' is used. For the 3 channels(int/float) of 3D, e.g. [[[0], [[1]], [[2]]], [[[0.], [[1.]], [[2.]]], etc, 'RGB', 'YCbCr' or 'HSV' is used. For the 4 channels(int/float) of 3D, e.g. [[[0], [[1]], [[2]], [[3]]], [[[0.], [[1.]], [[2.]], [[3.]]], etc, 'RGBA', 'CMYK' or 'RGBX' is used. The 1st argument is img(Required-Type:PIL Image, Image or tensor/ndarray(int/float/complex/bool)): *Memos: A tensor must be 2D or 3D. A ndarray must be 2D or 3D. Don't use img=. v2 is recommended to use according to V1 or V2? Which one should I use?. from torchvision.datasets import OxfordIIITPet from torchvision.transforms.v2 import ToPILImage import torch import numpy as np tp = ToPILImage() tp = ToPILImage(mode=None) tp # ToPILImage() print(tp.mode) # None Image_data = OxfordIIITPet( root="data", transform=ToImage() ) Tensor_data = OxfordIIITPet( root="data", transform=PILToTensor() ) tp = ToPILImage() tp(Image_data) # It's still `Image`. # Dataset OxfordIIITPet # Number of datapoints: 3680 # Root location: data # StandardTransform # Transform: ToImage() tp(Tensor_data) # It's still `tensor`. # Dataset OxfordIIITPet # Number of datapoints: 3680 # Root location: data # StandardTransform # Transform: ToTensor() tp(Image_data[0]) tp(Tensor_data[0]) # (, 0) tp((torch.tensor([[0, 1, 2, 3]]), 0)) # int64 tp((torch.tensor([[0, 1, 2, 3]], dtype=torch.int64), 0)) tp(torch.tensor([[0, 1, 2, 3]])) # TypeError: Input type int64 is not supported tp((torch.tensor([[0, 1, 2, 3]], dtype=torch.int32), 0)) tp((torch.tensor([[[0, 1, 2, 3]]], dtype=torch.int32), 0)) # (, 0) tp((torch.tensor([[0., 1., 2., 3.]]), 0)) # float32 tp((torch.tensor([[0., 1., 2., 3.]], dtype=torch.float32), 0)) tp((torch.tensor([[0., 1., 2., 3.]], dtype=torch.float64), 0)) # (, 0) tp((torch.tensor([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]]), 0)) # complex64 tp((torch.tensor([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]], dtype=torch.complex64), 0)) # TypeError: Input type complex64 is not supported tp((torch.tensor([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]], dtype=torch.complex32), 0)) # TypeError: Got unsupported ScalarType ComplexHalf tp((torch.tensor([[True, False, True, False]]), 0)) tp((torch.tensor([[True, False, True, False]], dtype=torch.bool), 0)) # TypeError: Input type bool is not supported tp((np.array([[0, 1, 2, 3]]), 0)) # int32 tp((np.array([[0, 1, 2, 3]], dtype=np.int32), 0)) # (, 0) tp((np.array([[0, 1, 2, 3]], dtype=np.int64), 0)) # TypeError: Input type int64 is not supported tp((np.array([[0., 1., 2., 3.]]), 0)) # float64 tp((np.array([[0., 1., 2., 3.]], dtype=np.float64), 0)) tp((np.array([[0., 1., 2., 3.]], dtype=np.float32), 0)) # (, 0) tp((np.array([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]]), 0)) tp((np.array([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]], dtype=np.complex128), 0)) # TypeError: Input type complex128 is not supported tp((np.array([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]], dtype=np.complex64), 0)) # TypeError: Input type complex64 is not supported tp((np.array([[True, False, True, False]]), 0)) # bool tp((np.array([[True, False, True, False]], dtype=bool), 0)) # TypeError: Input type bool is not supported

*Memos:
- My post explains how to convert and scale a PIL Image to an Image in PyTorch.
- My post explains Compose().
- My post explains ToImage().
- My post explains ToDtype().
- My post explains ToTensor().
- My post explains PILToTensor().
- My post explains OxfordIIITPet().
ToPILImage() can convert an Image([..., C, H, W]
), tensor or ndarray to a PIL(Pillow library) Image([H, W, C]
) and doesn't scale its values to [0.0, 1.0]
as shown below:
*Memos:
- The 1st argument for initialization is
mode
(Optional-Default:None
-Type:PIL.Image mode): *Memos:- If it's
None
, a mode is automatically set depending onimg
. - For the 1 channel(
int
) of 2D or 3D, e.g.[[0, 1, 2, 3]]
,[[[0]]]
, etc,'I'
is used. - For the 1 channel(
float
) of 2D or 3D, e.g.[[0], [1], [2], [3]]
,[[[0.]]]
, etc,'L'
is used. - For the 2 channels(
int
/float
) of 3D, e.g.[[[0], [[1]]]
,[[[0.], [[1.]]]
, etc,'LA'
is used. - For the 3 channels(
int
/float
) of 3D, e.g.[[[0], [[1]], [[2]]]
,[[[0.], [[1.]], [[2.]]]
, etc,'RGB'
,'YCbCr'
or'HSV'
is used. - For the 4 channels(
int
/float
) of 3D, e.g.[[[0], [[1]], [[2]], [[3]]]
,[[[0.], [[1.]], [[2.]], [[3.]]]
, etc,'RGBA'
,'CMYK'
or'RGBX'
is used.
- If it's
- The 1st argument is
img
(Required-Type:PIL Image
, Image ortensor
/ndarray
(int
/float
/complex
/bool
)): *Memos:- A tensor must be 2D or 3D.
- A ndarray must be 2D or 3D.
- Don't use
img=
.
-
v2
is recommended to use according to V1 or V2? Which one should I use?.
from torchvision.datasets import OxfordIIITPet
from torchvision.transforms.v2 import ToPILImage
import torch
import numpy as np
tp = ToPILImage()
tp = ToPILImage(mode=None)
tp
# ToPILImage()
print(tp.mode)
# None
Image_data = OxfordIIITPet(
root="data",
transform=ToImage()
)
Tensor_data = OxfordIIITPet(
root="data",
transform=PILToTensor()
)
tp = ToPILImage()
tp(Image_data) # It's still `Image`.
# Dataset OxfordIIITPet
# Number of datapoints: 3680
# Root location: data
# StandardTransform
# Transform: ToImage()
tp(Tensor_data) # It's still `tensor`.
# Dataset OxfordIIITPet
# Number of datapoints: 3680
# Root location: data
# StandardTransform
# Transform: ToTensor()
tp(Image_data[0])
tp(Tensor_data[0])
# (, 0)
tp((torch.tensor([[0, 1, 2, 3]]), 0)) # int64
tp((torch.tensor([[0, 1, 2, 3]], dtype=torch.int64), 0))
tp(torch.tensor([[0, 1, 2, 3]]))
# TypeError: Input type int64 is not supported
tp((torch.tensor([[0, 1, 2, 3]], dtype=torch.int32), 0))
tp((torch.tensor([[[0, 1, 2, 3]]], dtype=torch.int32), 0))
# (, 0)
tp((torch.tensor([[0., 1., 2., 3.]]), 0)) # float32
tp((torch.tensor([[0., 1., 2., 3.]], dtype=torch.float32), 0))
tp((torch.tensor([[0., 1., 2., 3.]], dtype=torch.float64), 0))
# (, 0)
tp((torch.tensor([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]]), 0)) # complex64
tp((torch.tensor([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]],
dtype=torch.complex64), 0))
# TypeError: Input type complex64 is not supported
tp((torch.tensor([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]],
dtype=torch.complex32), 0))
# TypeError: Got unsupported ScalarType ComplexHalf
tp((torch.tensor([[True, False, True, False]]), 0))
tp((torch.tensor([[True, False, True, False]], dtype=torch.bool), 0))
# TypeError: Input type bool is not supported
tp((np.array([[0, 1, 2, 3]]), 0)) # int32
tp((np.array([[0, 1, 2, 3]], dtype=np.int32), 0))
# (, 0)
tp((np.array([[0, 1, 2, 3]], dtype=np.int64), 0))
# TypeError: Input type int64 is not supported
tp((np.array([[0., 1., 2., 3.]]), 0)) # float64
tp((np.array([[0., 1., 2., 3.]], dtype=np.float64), 0))
tp((np.array([[0., 1., 2., 3.]], dtype=np.float32), 0))
# (, 0)
tp((np.array([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]]), 0))
tp((np.array([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]], dtype=np.complex128), 0))
# TypeError: Input type complex128 is not supported
tp((np.array([[0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j]], dtype=np.complex64), 0))
# TypeError: Input type complex64 is not supported
tp((np.array([[True, False, True, False]]), 0)) # bool
tp((np.array([[True, False, True, False]], dtype=bool), 0))
# TypeError: Input type bool is not supported