디지털 이미지의 구조와 PIL
실습 준비
PIL(Python Imaging Library)은 파이썬 이미지 처리 라이브러리임. 현재는 PIL을 계승한 Pillow를 설치하여 사용함. 파이썬에서 불러올 때는 기존 이름인 PIL을 사용함.
pip install pillow numpy
실습에서는 balloon.webp 파일을 현재 작업 폴더에 둠.
from pathlib import Path
import numpy as np
from PIL import Image, ImageOps
image_path = Path("balloon.webp")
img = Image.open(image_path)
img
이미지의 기본 속성
img.format: 디코더가 확인한 파일 형식. 실습 파일에서는WEBP- 파일 확장자와 실제 형식이 항상 일치한다고 가정하면 안 됨
img.format # 파일 형식
img.size:(가로, 세로)순서의 픽셀 크기
img.size # (가로, 세로)
img.mode: 픽셀 하나를 구성하는 채널의 종류
img.mode # 색상 모드
- 해상도: 이미지의 해상도는 보통
가로 픽셀 수 × 세로 픽셀 수로 표현함. 예를 들어 1920×1080 이미지는 총 2,073,600개의 픽셀로 구성됨.
width, height = img.size
pixel_count = width * height
width, height, pixel_count
컴퓨터 그래픽의 표현 방식
| 방식 | 표현 | 대표 용도 |
|---|---|---|
| 비트맵(bitmap) | 픽셀의 격자 | 사진, 동영상 프레임, 컴퓨터 비전 |
| 벡터(vector) | 수학적인 선과 도형 | 로고, 아이콘, 도면 |
| 포인트 클라우드(point cloud) | 3차원 좌표를 가진 점의 집합 | 라이다, 3차원 측량, 로봇 |
일반적인 이미지 처리와 컴퓨터 비전에서는 카메라가 만든 비트맵 이미지를 주로 사용함.
비트맵과 픽셀
비트맵은 이미지를 작은 점인 픽셀(pixel)의 격자로 표현함.
- 각 픽셀은 위치와 색상 값을 가짐
- 픽셀 수가 많을수록 같은 크기로 표시할 때 세부 표현이 정밀함
- 작은 비트맵을 크게 확대하면 새로운 세부 정보가 생기지 않아 픽셀 경계가 드러남
- 원점
(0, 0)은 왼쪽 위이며, 오른쪽으로 x 좌표, 아래쪽으로 y 좌표가 증가


PIL에서는 (x, y) 순서로 특정 픽셀을 조회함.
x = width // 2
y = height // 2
img.getpixel((x, y)) # 중앙 픽셀의 값
출력값의 개수는 이미지 모드에 따라 달라짐. RGB 이미지라면 (R, G, B), RGBA 이미지라면 (R, G, B, A) 형태임.
벡터 이미지
벡터 이미지는 픽셀 값 대신 선, 곡선, 도형을 수학적으로 표현함.
- 확대하거나 축소할 때 도형을 다시 계산하므로 경계가 선명함
- 로고와 아이콘처럼 형태가 명확한 그래픽에 적합
- 대표 형식: SVG, PDF, EPS
- 카메라 사진처럼 복잡한 장면은 일반적으로 비트맵으로 처리
포인트 클라우드
포인트 클라우드는 공간상의 점을 (x, y, z) 좌표로 표현함. 점마다 색상이나 반사 강도 같은 정보를 함께 저장할 수 있음.
- 라이다(LiDAR), 깊이 카메라, 3차원 스캐너에서 생성
- 자율 주행, 로봇, 건축 측량 등에 활용
- 일반적인 2차원 비트맵과 자료 구조가 다름

색상과 채널
컬러 비트맵은 픽셀마다 여러 채널(channel)의 값을 저장함. 화면에서는 빛의 삼원색인 빨강(R), 초록(G), 파랑(B)을 조합하는 RGB 방식을 주로 사용함.


| 모드 | 채널 | 용도 |
|---|---|---|
1 | 흑백 1비트 | 흑백 문서와 이진 마스크 |
L | 밝기 1채널 | 그레이스케일 이미지 |
RGB | 빨강·초록·파랑 3채널 | 화면 표시와 일반 컬러 이미지 |
RGBA | RGB와 알파 4채널 | 투명도가 있는 컬러 이미지 |
CMYK | 시안·마젠타·노랑·검정 4채널 | 인쇄 |
P | 색상표 인덱스 1채널 | 팔레트 기반 PNG와 GIF |
색상 모드는 다음과 같이 변환함.
그레이스케일로 변환:
gray = img.convert("L")
gray.mode
RGBA로 변환
rgba = img.convert("RGBA")
rgba.mode
비트 깊이와 픽셀 값
비트 깊이(bit depth)는 한 채널의 값을 표현하는 데 사용하는 비트 수임.
- 8비트 채널: 단계
uint8의 값 범위: 0–255L: 0은 검정, 255는 흰색RGB: 픽셀마다 8비트 채널 3개를 사용하므로 일반적으로 24비트RGBA: RGB와 8비트 알파 채널을 사용하므로 일반적으로 32비트
예를 들어 RGB 픽셀 (255, 0, 0)은 빨강, (255, 255, 255)는 흰색을 나타냄.
이미지 파일에서 픽셀 배열까지
이미지 파일은 픽셀 값을 그대로 나열한 것이 아니라 파일 형식에 따라 압축하고 구조화한 데이터임. 이미지 처리 전에 디코딩하여 메모리의 픽셀 배열로 변환함.
이미지 파일(JPEG·PNG·WebP)
↓ 디코딩
PIL Image 객체
↓ np.asarray()
NumPy 픽셀 배열
array = np.asarray(img)
array.shape # 배열 모양
array.dtype # 자료형
array.min(), array.max() # 최솟값과 최댓값
RGB 이미지라면 결과를 다음과 같이 해석함.
| 표현 | 순서 |
|---|---|
PIL img.size | (가로, 세로) |
NumPy array.shape | (세로, 가로, 채널) |
PIL img.getpixel((x, y)) | (x, y) 위치 |
NumPy array[y, x] | [y, x] 위치 |
img.getpixel((x, y)), array[y, x]
두 값은 같은 위치의 픽셀을 나타냄. PIL은 좌표를 (x, y)로 받고, NumPy는 행과 열 순서인 [y, x]로 접근함.
주요 비트맵 파일 형식
| 형식 | 압축 | 투명도 | 특징과 용도 |
|---|---|---|---|
| JPEG | 손실 | 지원하지 않음 | 사진에 적합, 품질과 파일 크기 조절 가능 |
| PNG | 무손실 | 지원 | 로고, 도표, 스크린샷, 투명 배경 |
| WebP | 손실·무손실 | 지원 | 웹 이미지, 애니메이션 지원 |
| GIF | 무손실·팔레트 기반 | 제한적 지원 | 단순한 애니메이션, 프레임당 최대 256색 |
| TIFF | 다양한 방식 | 형식에 따라 지원 | 스캔, 인쇄, 보존용 고품질 이미지 |
| RAW | 카메라별 센서 형식 | 해당 없음 | 카메라 센서의 원시 데이터, 현상 과정 필요 |
손실 압축(lossy compression)은 사람이 덜 민감한 정보를 일부 제거하여 파일을 작게 만듦. 무손실 압축(lossless compression)은 디코딩했을 때 원래 픽셀 값을 복원함.
RAW는 하나의 표준 확장자가 아니며 항상 무압축인 것도 아님. 제조사와 카메라에 따라 저장 구조가 다름.
알파 채널과 투명도
RGBA의 A는 알파(alpha) 채널임.
- 0: 완전히 투명
- 255: 완전히 불투명
- 중간값: 반투명
semi_transparent = img.convert("RGBA")
semi_transparent.putalpha(128)
semi_transparent.save("balloon_alpha.png")
semi_transparent
JPEG는 알파 채널을 저장하지 못함. 투명도가 필요하면 PNG 또는 알파를 지원하는 WebP 같은 형식을 사용함.