logo

NumPy 이미지 배열과 PIL 변환

실습 준비

pip install opencv-python pillow numpy

PIL 이미지와 OpenCV 이미지 배열을 함께 비교.

import cv2 as cv
import numpy as np
from PIL import Image

image_path = "balloon.webp"
img_pil = Image.open(image_path)
img_cv = cv.imread(image_path)

PIL 픽셀 값 조회

  • PIL에서는 (x, y) 순서로 특정 픽셀을 조회.
  • 원점 (0, 0)은 왼쪽 위이며, 오른쪽으로 x 좌표, 아래쪽으로 y 좌표가 증가.
width, height = img_pil.size
x = width // 2
y = height // 2

img_pil.getpixel((x, y))  # 중앙 픽셀의 값
실행 결과
(47, 108, 17)
  • 출력값의 개수는 이미지 모드에 따라 달라짐.
  • RGB 이미지라면 (R, G, B), RGBA 이미지라면 (R, G, B, A) 형태.

PIL 이미지를 NumPy 배열로 변환

  • 이미지 파일은 픽셀 값을 그대로 나열한 것이 아니라 파일 형식에 따라 압축하고 구조화한 데이터.
  • PIL로 디코딩한 이미지는 np.asarray()로 NumPy 픽셀 배열로 변환 가능.
이미지 파일(JPEG·PNG·WebP)
          ↓ 디코딩
PIL Image 객체
          ↓ np.asarray()
NumPy 픽셀 배열
array = np.asarray(img_pil)
array.shape  # 배열 모양
실행 결과
(1024, 1024, 3)
array.dtype  # 자료형
실행 결과
dtype('uint8')
array.min(), array.max()  # 최솟값과 최댓값
실행 결과
(np.uint8(0), np.uint8(255))

RGB 이미지라면 결과를 다음과 같이 해석.

표현순서
PIL img_pil.size(가로, 세로)
NumPy array.shape(세로, 가로, 채널)
PIL img_pil.getpixel((x, y))(x, y) 위치
NumPy array[y, x][y, x] 위치
img_pil.getpixel((x, y)), array[y, x]
실행 결과
((47, 108, 17), array([ 47, 108,  17], dtype=uint8))
  • 두 값은 같은 위치의 픽셀을 나타냄.
  • PIL은 파이썬 튜플로, NumPy는 배열로 반환하므로 표시 형태만 다름.
  • PIL은 좌표를 (x, y)로 받고, NumPy는 행과 열 순서인 [y, x]로 접근.

OpenCV 이미지 배열

OpenCV-Python에서 이미지는 NumPy 배열로 표현됨.

img_cv.shape  # (세로, 가로, 채널)
실행 결과
(1024, 1024, 3)
img_cv.dtype  # 픽셀 자료형
실행 결과
dtype('uint8')
img_cv.size  # 배열을 구성하는 전체 값의 개수
실행 결과
3145728

PIL과 OpenCV 배열에서 size의 의미가 다름.

표현의미
PIL img_pil.size(가로, 세로)
OpenCV img_cv.shape(세로, 가로, 채널)
NumPy img_cv.size세로×가로×채널인 전체 원소 수
height, width, channels = img_cv.shape
height, width, channels
실행 결과
(1024, 1024, 3)

일반적인 컬러 이미지는 uint8 자료형을 사용하며 채널마다 0–255 범위의 값을 가짐.

NumPy 배열을 PIL 이미지로 변환

PIL은 컬러 이미지를 RGB 순서로 다루지만, cv.imread()가 반환하는 컬러 배열은 기본적으로 BGR 순서.

PIL:    R, G, B
OpenCV: B, G, R
  • OpenCV 배열을 그대로 PIL 이미지로 만들면 빨강과 파랑이 뒤바뀌어 보임.
  • BGR 배열을 RGB로 변환한 뒤 Image.fromarray()에 전달.
rgb = cv.cvtColor(img_cv, cv.COLOR_BGR2RGB)
Image.fromarray(rgb)

BGR을 RGB로 변환하여 자연스러운 색으로 표시한 열기구 이미지

yeom으로 OpenCV 배열 표시

yeom 패키지의 to_pil()을 사용하면 별도의 표시 함수를 정의하지 않고 OpenCV 배열을 PIL 이미지로 변환 가능.

설치:

!pip install yeom

사용법:

from yeom import to_pil
to_pil(img_cv)
Previous
OpenCV와 이미지 입출력