λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ’» Programming/Computer Vision

[python] OpenCV, PIL, Numpy, PyTorch νƒ€μž… 뢄석, νƒ€μž… λ³€ν™˜ 정리

by 뭅즀 2022. 7. 21.
λ°˜μ‘ν˜•

# PIL

  • RGB νƒ€μž…μœΌλ‘œ 이미지 읽음
  • torchvision.transforms λͺ¨λ“ˆμ—μ„œ μ§€μ›ν•˜λŠ” 데이터 νƒ€μž…μ΄ PIL의 Image array μ΄λ―€λ‘œ pytorch ν”„λ ˆμž„μ›Œν¬ μ‚¬μš©μ‹œ PIL 둜 이미지λ₯Ό λ‘œλ”©ν•˜λŠ” 방식을 많이 μ‚¬μš©
  • numpy array 인덱싱 λΆˆκ°€λŠ₯ → 상황에 따라 numpy array둜 λ°”κΎΈκΈ° μœ„ν•œ μž‘μ—… ν•„μš” 
  • μ‚¬μ΄μ¦ˆ ν™•μΈμ‹œ .size() λ©”μ„œλ“œλ‘œ 확인 κ°€λŠ₯ν•œλ°, (W,H)둜 좜λ ₯됨. ν•˜μ§€λ§Œ, numpy array 둜 λ³€ν™˜μ‹œ (H,W,C)둜 λ‚˜μ˜€λ‹ˆκΉŒ 주의. 즉, .size()둜 확인 μ‹œμ—λ§Œ (W,H)둜 λ‚˜μ˜€λŠ” 것. 
from PIL import Image

image = Image.open("image.jpg").convert('RGB')
image.show()
image.save("saved_image.jpg")

 

 

# OpenCV

  • BGR νƒ€μž…μœΌλ‘œ 이미지 읽음
  • PIL에 λΉ„ν•΄ 더 λ§Žμ€ κΈ°λŠ₯(ν•¨μˆ˜) 지원
  • cv2 ν•¨μˆ˜μ— numpy array λ₯Ό input으둜 μ‚¬μš© κ°€λŠ₯ - numpy array μ™€μ˜ ν˜Έν™˜μ„± μ’‹μŒ
  • numpy array 인덱싱 μ‚¬μš© κ°€λŠ₯
  • torchvision 과의 ν˜Έν™˜μ„±μ€ 쒋지 μ•ŠμŒ
import cv2

BGR_image = cv2.imread("image.jpg")
RGB_image = cv2.cvtColor(BGR_image, cv2.COLOR_BGR2RGB)
gray_image = cv2.imread("image.jpg",0)

cv2.imshow('color image', BGR_image)
cv2.waitkey(0)

cv2.imshow('gray image', gray_image)
cv2.waitkey(0)

cv2.imwrite('saved_image.jpg', color_image)

 

# Matplotlib

import matplotlib.pyplot as plt

image = plt.imread('image.jpg')

plt.imshow(image)
plt.show()

 

# PyTorch image tensor

  • C x H x W ꡬ쑰
  • ν”½μ…€ 밝기 값이 0~1 λ²”μœ„

 

# νƒ€μž… λ³€ν™˜

이미지 μ „μ²˜λ¦¬λ₯Ό ν•˜κ±°λ‚˜ λ”₯λŸ¬λ‹ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” 데이터 νƒ€μž… λ³€ν™˜μ„ 자주 μ‚¬μš©ν•˜κ²Œ λ˜λŠ”λ° λͺ‡κ°€μ§€ μ£Όμ˜μ‚¬ν•­μ΄ μžˆλ‹€.

 

  • 일반적인 이미지 λ°μ΄ν„°λŠ” (H,W,C) 순의 0~255 ν”½μ…€κ°’μœΌλ‘œ μ €μž₯이 λ˜λŠ”λ°, PyTorch Tensor 의 경우 (C,H,W) 순의 0~1둜 μ •κ·œν™”λ˜μ–΄ μ‚¬μš©
  • PIL image / Numpy array νƒ€μž…μ„ PyTorch Tensor 둜 λ³€κ²½ν•΄μ£ΌλŠ” torchvision.transforms.ToTensor() ν•¨μˆ˜μ˜ 경우 (H,W,C), 0~255 픽셀값을 μžλ™μœΌλ‘œ (C,H,W), 0~1 ν”½μ…€κ°’μœΌλ‘œ λ³€ν™˜ν•΄μ£Όκ³ , λ‹€μ‹œ PyTorch Tensor λ₯Ό PIL image νƒ€μž…μœΌλ‘œ λ³€κ²½ν•΄μ£ΌλŠ” torchvision.transforms.ToPILImage() ν•¨μˆ˜ λ˜ν•œ (C,H,W), 0~1 픽셀값을 (H,W,C), 0~255 둜 λ³€ν™˜
  • ν•˜μ§€λ§Œ, κΈ°μ‘΄ λ©”λͺ¨λ¦¬λ₯Ό κ·ΈλŒ€λ‘œ 상속받아 numpy arrayλ₯Ό PyTorch Tensor 둜 λ³€ν™˜ν•΄μ£ΌλŠ” torch.from_numpy() ν•¨μˆ˜μ˜ 경우 numpy array의 인덱슀 μˆœμ„œμ™€ 픽셀값이 μœ μ§€λ˜κΈ° λ•Œλ¬Έμ— 사전에 채널좕과 픽셀값을 μ‘°μ •ν•˜λŠ” 과정이 ν•„μš”

 

 

*정리

  • PIL image / Numpy array → PyTorch Tensor (채널 μΆ•, ν”½μ…€ κ°’ λ²”μœ„ λ³€κ²½ O) : torchvision.transforms.ToTensor()
  • PyTorch Tensor → PIL image (채널 μΆ•, ν”½μ…€ κ°’ λ²”μœ„ λ³€κ²½ O) : torchvision.transforms.ToPILImage()
  • Numpy array → PyTorch Tensor (채널 μΆ•, ν”½μ…€ κ°’ λ²”μœ„ λ³€κ²½ X) : torch.from_numpy()
  • PIL image / OpneCV image / PyTorch Tensor → Numpy array : np.array(input_data)
from PIL import Image
import numpy as np
import cv2
import matplotlib.pyplot as plt
import torch
from torchvision.transforms import ToTensor, ToPILImage

image_PIL = Image.open("image.jpg")
image_PIL = image_PIL.convert('RGB')

image_plt = plt.imread('image.jpg')

image_numpy = np.array(image_PIL)
image_numpy_to_PIL = Image.fromarray(image_numpy)

image_cv_BGR = cv2.imread("image.jpg")
image_cv_RGB = cv2.cvtColor(image_cv_BGR, cv2.COLOR_BGR2RGB)

ToPILImage_ = ToPILImage() 
ToTensor_ = ToTensor()

# torchvision.transforms.ToTensor() : PIL/numpy -> PyTorch Tensor 
PIL_ToTensor_tensor = ToTensor_(image_PIL) # H,W,C, 0~255 -> C,H,W, 0~1
Numpy_ToTensor_tensor = ToTensor_(image_numpy) # H,W,C, 0~255 -> C,H,W, 0~1

# torch.from_numpy() : numpy array -> PyTorch Tensor 둜 λ³€ν™˜ μ‹œ κΈ°μ‘΄ λ©”λͺ¨λ¦¬ 상속
Numpy_to_tensor_from_numpy = torch.from_numpy(image_numpy)

# PyTorch Tensor to numpy array
PIL_ToTensor_tensor_to_Numpy = np.array(PIL_ToTensor_tensor)
Numpy_ToTensor_tensor_to_Numpy = np.array(Numpy_ToTensor_tensor)


# torchvision.transforms.ToPILImage() : PyTorch Tensor -> PIL  
img_PIL_from_Tensor = ToPILImage_(PIL_ToTensor_tensor) # C,H,W, 0~1 -> H,W,C, 0~255

 

* https://github.com/ethereon/lycon 의 benchmark λ₯Ό 보면 μ—¬λŸ¬ ν•¨μˆ˜μ˜ 처리 속도가 opencv κ°€ μ›”λ“±νžˆ 쒋은 것을 λ³Ό 수 있음.

 

λ°˜μ‘ν˜•