[Torchvision / PIL] torch.Tensor <-> PIL Image

olxtar·2022년 5월 31일
0
post-thumbnail

이미지는 아래와 같이 3가지의 종류가 있다 (더 많은 종류의 이미지 불러오는 방식이나 타입이 있지만 일단 이 3가지만 집중)

  1. PIL Image
  2. Numpy Array Image
  3. PyTorch Tensor Image




1. PIL Image & Numpy Array Image


먼저 PIL ImageNumpy Array Image는 아래와 같은 구조를 가지고 있다.

  • Height x Width x Depth(=Channel)
    • Height : 높이 Pixel수
    • Width : 넓이 Pixel수
    • Depth : 이미지의 '장'수 느낌, RGB의 경우 3장, Gray-scale의 경우 0 또는 1
  • Pixel value 범위 : 0 ~ 255







2. PyTorch Tensor Image


이에 반해 PyTorch Tensor Image는 아래와 같은 구조를 가지고 있다.

  • Depth(=Channel) x Height x Width
  • Pixel value 범위 : 0 ~ 1








3. Convert


3-0. 사용할 이미지


- Settings

import PIL
from PIL import Image

import numpy as np
import torchvision

- Image load and Visualization

img = Image.open('이미지파일 경로')
img


- Image info check

print(f"Image file format : {img.format}")
print(f"Image size : {img.size}")
print(f"Image colormode : {img.mode}")

>>>
Image file format : JPEG
Image size : (800, 533)
Image colormode : RGB

해당 이미지는 Color Mode가 RGB이므로

  • width(넓이) : 800 pixel
  • height(높이) : 533 pixel
  • depth(채널) : 3

print(type(img))

>>>
PIL.JpegImagePlugin.JpegImageFile

[!] PIL로 불러왔으므로 현재 img의 타입은 PIL Image 이다




3-1. PIL to Numpy Array


How to Convert PIL image to Numpy Array image

img_array = np.array(img) : PIL Image가 할당된 변수를 그냥 np.array()에 넣어주면 된다.

print(img_array)
print(f"Image array shape : {img_array.shape}")

>>>
array([[[ 42,  25,  18],
        [ 43,  26,  19],
        [ 50,  33,  26],
        ..., 
        [ 87,  70,  62],
        [ 74,  54,  45],
        [ 71,  51,  42]],
        
        ...
        
        [111,  82,  66],
        [111,  82,  68],
        [103,  75,  61]]], dtype=uint8)
        
Image array shape : (533, 800, 3)

[!] 먼저 Pixel value들이 매우 큰 0과 1사이가 아닌 값임을 볼 수 있다.
[!] 또한 Image Numpy array의 shape을 보면

  • Height x Width x Depth 순임을 알 수 있다.



3-2. Numpy Array to PIL


How to Convert Numpy Array image to PIL image

img_1 = Image.fromarray(img_array) : NumPy Array가 할당된 변수를 그냥 PIL.Image.fromarray()에 넣어주면 된다.

print(type(img_1))

>>>
PIL.Image.Image



3-3. PIL & Numpy Array to PyTorch Tensor


How to Convert PIL & Numpy Array image to PyTorch Tensor

  1. 먼저 아래와 같이 object를 만들어줘야 한다.
    totensor = torchvision.transforms.ToTensor()

  2. PIL & Numpy Array가 할당된 변수를 object에 넣어준다.
    tensor_pil = totensor(img)
    tensor_numpy = totensor(img_array)

totensor = torchvision.transforms.ToTensor()   # object? 생성

tensor_pil = totensor(img)                     # PIL image -> Tensor 변환
tensor_numpy = totensor(img_array)             # Numpy Array image -> Tensor 변환

print(tensor_pil)
print(tensor_numpy.shape)                      # tensor_pil = tensor_numpy이므로 

>>>
tensor([[[ 0.1647,  0.1686,  0.1961,  ...,  0.3412,  0.2902,  0.2784],
         [ 0.2000,  0.1804,  0.2078,  ...,  0.3451,  0.3294,  0.3412],
         [ 0.2275,  0.1882,  0.2235,  ...,  0.2275,  0.2863,  0.3569],
         ...,
      
         [ 0.1529,  0.2275,  0.2706,  ...,  0.1569,  0.1529,  0.1451],
         [ 0.1412,  0.2039,  0.2392,  ...,  0.2471,  0.2196,  0.1608],
         [ 0.1490,  0.1647,  0.2000,  ...,  0.2588,  0.2667,  0.2392]]])
         
torch.Size([3, 533, 800])

[!] 먼저 Pixel value들이 0과 1사이의 범위로 변한 것을 볼 수 있다.
[!] 또한 Tensor의 size를 보면

  • Depth x Height x Width임을 볼 수 있다.



3-5. PyTorch Tensor to PIL


How to Convert PyTorch Tensor to PIL image

  1. 먼저 아래와 같이 object를 만들어줘야 한다.
    topilimage = torchvision.transforms.ToPILImage()

  2. image Tensor가 할당된 변수를 object에 넣어준다.
    img_pil = topilimage(tensor_pil)

img_array = np.array(img_pil)
print(img_array)
print(img_array.shape)

>>>
[[[ 42  25  18]
  [ 43  26  19]
  [ 50  33  26]
  ..., 

  [111  82  66]
  [111  82  68]
  [103  75  61]]]
  
(533, 800, 3)

Tensor \rightarrow PIL image \rightarrow Numpy Array로 확인한 결과
Pixel value도 0~255범위로 돌아오고
Shpae도 Height x Width x Depth로 잘 변한 것을 볼 수 있다.



2022/06/13 추가

[+]
Tensor로 변환된 이미지를 Numpy array로 바꿔야할 시 타입 문제가 일어날 수 있다.
그럴때는 해당 Array를 array.astype(np.uint8)을 통해 타입을 변경시켜 주자.

[+]
Numpy array를 시각화할때에는 plt.show()가 아닌 plt.imshow()를 사용하자

profile
예술과 기술

0개의 댓글