The basis of PIL library
When torchVision.transforms is used, the Image type typically used for the data enhancement is pil.image. Therefore, if you use imageio or SkImage library to read an image of type NP. ndarray, you need to convert it. This section is to make a simple summary of PIL library.
Basic information about the Image
Shape and type
The common module in PIL library is the Image module. There are two ways to read images: image.open () or image.fromarray ().
img = imageio.imread("0.jpg")
img1 = Image.fromarray(img)
img2 = Image.open("0.jpg")
Copy the code
The type of img1 or img2 is
, not NP.array. The shape is HWC. Data enhancements in TorchVision.transforms use PIL images by default, so if nP.ndarray is read in, they need to be converted to pil.image.
attribute
image = Image.open("0.jpg")
print('width: ', image.width)
print('height: ', image.height)
print('size: ', image.size)
print('mode: ', image.mode)
print('format: ', image.format)
print('category: ', image.category)
print('readonly: ', image.readonly)
print('info: ', image.info)
#output
width: 320
height: 223
size: (320.223)
mode: RGB
format: JPEG
category: 0
readonly: 1
info: {'jfif': 257.'jfif_version': (1.1), 'dpi': (72.72), 'jfif_unit': 1.'jfif_density': (72.72)}
Copy the code
The data format
The data stored in PIL is stored in the format of Uint8, which represents eight-bit unsigned numbers ranging from 0 to 255. If this format condition is not met during conversion, an error is reported.
PIL library basic function operations
To add…
PIL and NUMpy convert to each other
Why conversion is needed
Libraries commonly used to read images include Imageio and Skimage, as well as CV2, whose data types are shown below. Because torchVision.Transforms used PIL as the default image processing library, we needed to transform NP.ndarray to PIL processing. Pil. Image and Np. ndarray can be converted to each other. Shape remains HWC during conversion.
img_ski = io.imread("0.jpg")
img_cv2 = cv2.imread("0.jpg")
img_imgIO = imageio.imread("0.jpg")
print(type(img_ski))
print(type(img_cv2))
print(type(img_imgIO))
#output:
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>
<class 'imageio.core.util.Array'>
Copy the code
Note:imageio.core.util.Array
Type, which is a subtype of Np.darray. 【 stackoverflow 】
imageio.core.util.Array is a subclass of the NumPy array, so it is correct to say that imread returns a NumPy array. You can find the source code for Array at Github.com/imageio/ima… .
Image and NP.ndarray conversion
The Image converted to np. Ndarray
image = Image.open("0.jpg")
img = np.array(image)
print(img.shape)
#output:
(223, 320, 3)
Copy the code
Np. Ndarray into the Image
img = imageio.imread("0.jpg")
img1 = Image.fromarray(img)
img1.show()
Copy the code
Type error:
img = np.ones((448.448.3))
print(img.dtype)
img1 = Image.fromarray(img)
# the output:
float64
Copy the code
TypeError: Cannot handle this data type: (1.1.3), <f8
Copy the code
As you can see from the above output, IMG has a data type of FLOAT64, while PIL needs a data type of Uint8, so an error is reported. The modification mode is:
img = np.ones((448.448.3))
print(img.dtype)
img2 = Image.fromarray(np.uint8(img))
Copy the code
PIL and transforms
Transforms is a data enhancement library in Torch. Common libraries for PIL are ToPILImage and ToTensor.
ToPILImage
The need for ToPILImage is to translate Np. ndarray or tensor into Pil. Image, where you do a channel conversion, and then HWC.
Npimg = PIC if isinstance(PIC, torch.FloatTensor) and mode! = 'F': pic = pic.mul(255).byte() if isinstance(pic, torch.Tensor): npimg = np.transpose(pic.numpy(), (1, 2, 0))Copy the code
ToTensor
The tensor default is CHW. This has already been done at ToTensor(), so you don’t need to do anything else.
But at show you have a tensor shape of CHW, and then you need HWC in Matplotlib so you have to translate it back.
def to_tensor(pic) :
"""Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor. Args: pic (PIL Image or numpy.ndarray): Image to be converted to tensor. Returns: Tensor: Converted image. """.# ---------# handle numpy array------------
if isinstance(pic, np.ndarray):
if pic.ndim == 2:
pic = pic[:, :, None]
img = torch.from_numpy(pic.transpose((2.0.1))) This is the transformation
# backward compatibility
if isinstance(img, torch.ByteTensor):
return img.float().div(255)
else:
return img
......
# -----------handle PIL Image----------------
Here you can see that the conversion from PIL to Torch at tensor was done through nP.array.
if pic.mode == 'I':
img = torch.from_numpy(np.array(pic, np.int32, copy=False))
elif pic.mode == 'I; 16 ':
img = torch.from_numpy(np.array(pic, np.int16, copy=False))
elif pic.mode == 'F':
img = torch.from_numpy(np.array(pic, np.float32, copy=False))
elif pic.mode == '1':
img = 255 * torch.from_numpy(np.array(pic, np.uint8, copy=False))
else:
img = torch.ByteTensor(torch.ByteStorage.from_buffer(pic.tobytes()))
img = img.view(pic.size[1], pic.size[0].len(pic.getbands()))
# put it from HWC to CHW format
img = img.permute((2.0.1)).contiguous() # Here is the conversion
if isinstance(img, torch.ByteTensor):
return img.float().div(255)
else:
return img
Copy the code
Summary: This time recorded three aspects of content, respectively PIL base content, PIL and NP.nDARray transformation, PIL in the transforms of the two classes. PIL reads data with basic information, such as shape as HWC, data type as Uint8, and some basic attributes. When reading data, the read type is usually NP.ndarray, so the pil. Image Image needs to be converted. Transforms transforms ToPILImage, which transforms NP. ndarray or tensor into PIL, where it changes the channel to HWC, and ToTensor, which transforms PIL into tensor and changes the channel at the same time.
Collection of links
Zodiac Wang (Zodiac911.github. IO)
The difference between different functions in Python that read image formats _u013044310 blog-csdn blog_img. astype
Convert Numpy, Opencv and pil. Image formats to each other _Onwaier blog -CSDN blog _numpy to Opencv
Pytorch: On numpy and PIL conversion issues _ Ryuki Sakura’s blog -CSDN blog