2장. 이미지 입출력과 영상 시각화
영상 데이터의 구조
택배 상자를 받으면 상자 옆의 표를 봅니다. 가로, 세로, 높이, 무게, 내용물이 적혀 있습니다. 상자를 열지 않아도 무엇이 얼마나 들었는지 압니다. OpenCV 가 돌려준 배열(ndarray)에도 이런 표가 붙어 있습니다. 배열에게 물어보면 모양, 자료형, 숫자 개수, 메모리 크기를 바로 답합니다.
그림의 다섯 상자가 배열에게 물어볼 수 있는 다섯 가지입니다. 여기서 택배 상자의 가로·세로·높이가 shape, 내용물의 종류가 dtype, 물건 개수가 size, 무게가 nbytes 입니다. 아래 띠의 식처럼 메모리 크기는 세로, 가로, 채널을 곱한 값에 숫자 하나의 크기(uint8 은 1바이트)를 곱해 구합니다.
다섯 가지 속성
| 속성 | 원래 말 | 뜻 | 320×240 컬러 그림이면 |
|---|---|---|---|
img.shape | shape(모양) | (세로, 가로, 채널) | (240, 320, 3) |
img.dtype | data type(자료형) | 칸 하나의 자료형 | uint8 |
img.size | size(크기) | 숫자의 총 개수 | 240×320×3 = 230,400 |
img.nbytes | number of bytes(바이트 수) | 메모리에서 차지하는 바이트 | 230,400 × 1 = 230,400 |
img.ndim | number of dimensions(차원 수) | 방향의 수 | 3 (흑백이면 2) |
손으로 계산해 보기
투명 스티커(160×160, 채널 4)의 메모리 크기를 손으로 구해 봅니다. 160 × 160 = 25,600칸이고, 칸마다 숫자가 4개이니 25,600 × 4 = 102,400개입니다. 숫자 하나가 1바이트이므로 102,400바이트, 1,024 로 나누면 100KB 입니다. 같은 스티커를 흑백으로 읽으면 채널이 1개라 25,600바이트(25KB)로 4분의 1이 됩니다.
import cv2
img = cv2.imread("ch02_sticker.png", cv2.IMREAD_UNCHANGED)
h, w, c = img.shape
print("모양:", img.shape, "차원 수:", img.ndim, "자료형:", img.dtype)
print("손 계산:", h * w * c, "바이트")
print("nbytes:", img.nbytes, "바이트") # 결과: 102400 → 손 계산과 같다
print("KB:", img.nbytes / 1024) # 결과: 100.0주의할 점
- 흑백 그림은
shape가 (세로, 가로) 두 칸뿐입니다.h, w, c = img.shape로 세 개를 받으면 오류가 납니다. 흑백과 컬러가 섞여 있으면h, w = img.shape[:2]로 앞의 두 칸만 받습니다. - 파일 크기(디스크)와
nbytes(메모리)는 다릅니다. 파일은 압축돼 있고, 읽으면 압축이 풀려 메모리에서는 늘 세로×가로×채널 바이트를 차지합니다.