파이썬 이미지 처리 라이브러리 비교 | PIL, OpenCV, Numpy, PyTorch, Albumentations
1. PIL (Pillow)
Python Imaging Library(PIL)은 이미지 처리를 위한 오픈소스 라이브러리입니다. Pillow는 PIL의 확장된 버전으로 이미지 파일 입출력 및 기본적인 처리 작업을 지원합니다. 다양한 이미지 포맷(JPEG, PNG, BMP 등)을 지원하고, 크기 조정이나 회전 등 간단한 이미지 처리가 가능합니다. [1]
PIL에서는 데이터를 PIL.Image 객체로 관리해 필요할 때마다 불러옵니다. 파이썬에서 많이 사용하는 형식인 NumPy와 변환을 위해서 아래와 같은 방법을 이용할 수 있습니다.
from PIL import Image
import numpy as np
# PIL → NumPy
image_pil = Image.open('image.jpg')
image_np = np.array(image_pil)
# NumPy → PIL
image_pil_converted = Image.fromarray(image_np)
2. OpenCV
OpenCV는 2000년에 최초로 공개된 이미지 처리를 위한 소프트웨어로 C++로 구현되어 있지만, 파이썬이나 자바 등 다양한 프로그래밍 언어를 지원합니다. 파이썬에서 이미지를 다루기 위해서 최근에 사용해보신 분이라면 cv2라는 라이브러리 형태로 사용해본 적이 있을 겁니다.
OpenCV의 강점 중 하나는 다양한 이미지 분석 및 컴퓨터 비전 알고리즘을 제공한다는 점일 것입니다. 필터링, 엣지 검출, 변환 등 옛날부터 연구된 이미지 처리 알고리즘이나 CNN을 통해서나 접했던 특징 추출을 알고리즘으로도 가능합니다. [2]
cv2를 통한 이미지는 NumPy 다차원 배열(ndarray)을 통해 반환됩니다. NumPy는 기본적으로 [H, W, C] 구조로 저장을 하게 되는데, 그중에서 cv2는 채널(C)에 대해 통상적으로 익숙한 RGB가 아니라 BGR 순서로 처리합니다. 그렇기 때문에 RGB 채널이 필요할 경우 아래와 같은 방법을 통해 변환이 필요합니다.
import cv2
from PIL import Image
# OpenCV (BGR) → Pillow (RGB)
image_cv2 = cv2.imread('image.jpg')
image_rgb = cv2.cvtColor(image_cv2, cv2.COLOR_BGR2RGB)
image_pil = Image.fromarray(image_rgb)
# Pillow (RGB) → OpenCV (BGR)
image_np = np.array(image_pil)
image_bgr = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
참고로, EDA를 수행할 때 Jupyter Notebook을 많이 사용할텐데, cv2에서 이미지를 보여주는 기능인 cv2.imshow()는 잘 동작하지 않습니다.[3] 따라서, 저같은 경우는 NumPy 배열을 동시에 잘 활용할 수 있는 matplotlib 라이브러리를 통해 시각화를 많이 수행하고 있습니다. 이 경우에 제대로 색으로 이미지를 보기 위해선 반드시 RGB로 변환이 필요합니다.
3. PyTorch (Torchvision)
PyTorch는 대표적인 딥러닝 프레임워크로 데이터 전처리부터 모델 학습까지 모두 통합된 작업 환경을 제공하고 있습니다. Torchvision은 PyTorch 프로젝트의 한 부분으로 유명한 이미지 데이터셋, 모델 구조, 공통적인 변환을 위한 컴퓨터 비전 기능을 제공하고 있습니다. 편하게 GPU 학습을 진행하고 텐서 연산을 진행하기 위해서는 PyTorch 프레임워크에 맞는 데이터로 전환하는 과정이 Dataset을 통해 이뤄져야 합니다.
PyTorch 프레임워크에서는 이미지 데이터를 텐서(torch.Tensor) 형태로 이용합니다. 따라서, 위 두가지 라이브러리에서 이용하는 NumPy 데이터를 텐서로 바꾸는 과정이 필요합니다. 역으로 학습이 된 데이터를 NumPy 배열로 바꿔야 할 수도 있습니다.
아래 코드는 PyTorch와 NumPy 사이 변환을 나타내는 예제 코드입니다. 텐서는 주로 [C, H, W] 구조로 이뤄져 있기 때문에 NumPy의 [H, W, C]에 맞게끔 변환하기 위해 permute를 사용했습니다. [4]
import torch
import numpy as np
# NumPy → PyTorch 텐서
image_tensor = torch.from_numpy(image_np)
image_tensor = image_tensor.permute(2, 0, 1) # [H, W, C] → [C, H, W]
# PyTorch 텐서 → NumPy
image_np = image_tensor.permute(1, 2, 0).numpy() # [C, H, W] → [H, W, C]
조금 더 나아가서 PIL로 이미지를 읽고 텐서로 바꾸는 예제를 살펴보겠습니다. 1번 과정에서 NumPy로 바꾸고 처리하는 방법도 있겠지만, torchvision에서 제공하고 있는 ToTensor를 이용할 수 있습니다.
import torchvision.transforms.v2 as transforms
from PIL import Image
# PIL → PyTorch 텐서
image_pil = Image.open('image.jpg')
transform = transforms.ToTensor()
image_tensor = transform(image_pil)
# PyTorch 텐서 → PIL
image_pil_converted = transforms.ToPILImage()(image_tensor)
4. Albumentations
Albumentations는 엄밀하게는 이미지를 읽는데 필요하진 않지만, 데이터 증강에 필요한 많은 기능을 제공하는 대표적인 데이터 증강 라이브러리 입니다. Torchvision에서도 제공하지만 기능이 상대적으로 적은 편인 것 같고, cv2보다는 훨씬 쓰기 편한 것 같아 자주 애용합니다. (특히, 객체 탐지에서 bbox나 세그멘테이션의 마스크 관련 처리 기능을 함께 제공해서 매우 편하게 사용할 수 있는 라이브러리라 생각합니다)
Albumentations는 NumPy 배열을 사용합니다. 따라서 증강 이후 훈련에 사용해야 하는 On-line Augmentation을 수행해야 할 때는 PyTorch로 바꿔야 합니다. 방법은 아래와 같이 가능합니다.
import albumentations as A
from albumentations.pytorch import ToTensorV2
# Albumentations 증강 정의
transform = A.Compose([
A.Resize(256, 256),
A.HorizontalFlip(p=0.5),
A.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)),
ToTensorV2() # NumPy → PyTorch 텐서
])
# NumPy 이미지에 증강 적용
augmented = transform(image=image_np)
image_tensor = augmented['image']
5. 정리
앞서 한꺼번에 볼 수 있도록 정리하면 아래와 같습니다.
라이브러리 | 데이터 형식 | 대표적인 데이터 변환 방법 |
Pillow | PIL.Image | - np.array(image) → NumPy 배열로 변환. - Image.fromarray(array) → PIL 이미지로 변환. |
OpenCV | NumPy(BGR) | - cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
PyTorch | torch.Tensor | - image.numpy() → NumPy 배열. - transforms.ToTensor() → PIL 이미지를 텐서로. |
Albumentations | NumPy | NumPy 기반의 증강 후 PyTorch 텐서로 변환 (ToTensorV2()) |
6. 참고 자료
[1] https://pillow.readthedocs.io/en/stable/index.html
[2] https://docs.opencv.org/4.x/d0/de3/tutorial_py_intro.html
[3] https://stackoverflow.com/questions/46236180/opencv-imshow-will-cause-jupyter-notebook-crash
[4] https://discuss.pytorch.org/t/using-torchvision-transforms-with-numpy-arrays/184688
'Python > Data Prep' 카테고리의 다른 글
Pydantic을 활용 사례 | 웹 데이터 검증, Config 관리 (2) | 2024.12.14 |
---|---|
DeepL을 활용해서 외국어 OCR 영수증 데이터셋 합성하기 (2) | 2024.11.09 |
[OD] 객체 탐지(Object Detection) 대표 데이터 포맷 공부 | COCO, Pascal VOC, YOLO (0) | 2024.10.04 |
DataLoader에서 오류가 난다면 누락 데이터가 있는지 확인 필요 | DataLoader는 이터레이터 (2) | 2024.09.26 |
PyTorch에서 Dataset과 DataLoader 클래스를 활용해 데이터 파이프라인 구축하기 (1) | 2024.09.09 |