OpenCV 비전 실무2장 · 이미지 입출력과 영상 시각화3 / 21← 이전목차다음 →MetaContents

2장. 이미지 입출력과 영상 시각화

그림 파일의 형식과 압축

여행 가방을 싸는 세 사람이 있습니다. 첫째는 옷을 반듯하게 개어 빈틈없이 넣습니다. 풀어 보면 옷이 그대로입니다. 둘째는 가방을 작게 하려고 자주 안 입는 옷을 몇 벌 빼고, 나머지를 꾹꾹 눌러 담습니다. 가방은 가볍지만 뺀 옷은 돌아오지 않습니다. 셋째는 개지도 않고 옷을 그냥 쌓아 넣습니다. 가방이 가장 큽니다. 그림 파일의 세 형식이 이 세 사람과 같습니다.

PNG, JPG, BMP 세 형식의 압축 방식과 쓰임을 나란히 놓은 비교 그림

그림의 세 상자가 왼쪽부터 PNG, JPG, BMP 입니다. 여기서 옷을 반듯하게 개는 사람이 PNG(무손실 압축), 옷을 빼고 눌러 담는 사람이 JPG(손실 압축), 그냥 쌓는 사람이 BMP(압축 없음)입니다. 비유와 다른 점도 있습니다. JPG 가 버리는 것은 옷 한 벌처럼 통째가 아니라, 칸마다 숫자를 조금씩 뭉뚱그리는 것입니다.

같은 상품 그림의 글자 부분을 PNG, JPG 품질 50, JPG 품질 5 로 저장해 크게 키워 견준 그림

두 번째 그림은 같은 그림을 세 가지로 저장해 글자 부분을 크게 키운 것입니다. 왼쪽 PNG 는 글자 둘레가 깨끗합니다. JPG 는 품질을 낮출수록 글자 둘레에 얼룩과 네모난 덩어리가 생깁니다. JPG 는 그림을 8×8 칸씩 묶어 그 안의 잔무늬를 덜어 내기 때문입니다.

세 형식 견주기

견줄 것PNGJPG (JPEG)BMP
압축무손실손실없음
다시 읽은 숫자원본과 똑같다원본과 조금 다르다원본과 똑같다
파일 크기중간 (단순한 그림은 아주 작다)작다 (품질로 조절)가장 크다
투명도(알파)담을 수 있다담지 못한다보통 쓰지 않는다
알맞은 그림도형, 글자, 화면 캡처, 정답 표시 그림사진, 색이 부드럽게 이어지는 그림아주 오래된 프로그램과 주고받을 때

메모리 안에서 크기 견주기

cv2.imencode 는 그림을 파일 꼴의 바이트로 바꿔 주기만 하고 디스크에는 쓰지 않습니다. 돌려받은 바이트의 길이가 곧 그 형식으로 저장했을 때의 파일 크기입니다.

Python
import cv2

img = cv2.imread("ch02_market.png")      # 320×240 컬러 그림
print("메모리 속 배열:", img.nbytes, "바이트")

# 확장자만 바꿔 세 형식으로 인코딩한다. ok 는 성공 여부, buf 는 바이트 묶음
for ext in (".bmp", ".png", ".jpg"):
    ok, buf = cv2.imencode(ext, img)
    print(f"{ext:5} {len(buf):>7,}바이트")

BMP 는 배열 크기(230,400바이트)에 머리 정보 54바이트를 붙인 만큼이 되고, PNG 와 JPG 는 그보다 열 배 넘게 작습니다. 이 그림은 넓은 면을 한 가지 색으로 칠한 단순한 그림이라, 무손실인 PNG 도 JPG(옵션을 주지 않으면 품질 95)와 비슷한 크기까지 줄어듭니다.

주의할 점

  • JPG 를 열었다가 다시 JPG 로 저장하면 그때마다 조금씩 더 버립니다. 손질하는 중간 결과는 PNG 로 두고, 마지막에 한 번만 JPG 로 저장합니다.
  • 확장자를 .png 로 바꿔 이름만 고친다고 형식이 바뀌지 않습니다. 형식은 저장할 때(imwrite) 정해집니다.
← 이전 절2장 · 용어 짚고 가기다음 절 →2장 · 읽기 모드와 투명 채널