카테고리 없음

0810 디코드랩 정리(AI Engineering 07)

인뽕 2026. 8. 11. 14:16

 

 

07

업무 자동화 ② 사진 (1) — 한 장을 열고 줄인다

 

폴더를 훑고, 하나씩 열고, 바꿔서, 저장한다. 앞 강의와 틀이 똑같은데 대상이 사진으로 바뀐다. 먼저 한 장을 열어 크기를 재고, 줄여서, 용량이 얼마나 달라지는지 본다.

앞 두 강의에서 폴더를 훑어 엑셀을 만들었다. 이번에도 틀은 똑같다.

폴더를 훑는다  →  하나씩 연다  →  바꾼다  →  저장한다

 

바뀌는 건 다루는 대상이 글자에서 사진으로 바뀌는 것뿐이다.

 

 

이번 강의는 한 장을 제대로 다루고, 다음 강의에서 그걸 폴더째 돌린다.

 

pip install pillow

 

파일은 계속 ai-course 폴더에 넣는다. 이번 강의는 71번부터다.

 

설치는 pillow 인데 코드에서는 from PIL import ... 로 부른다. 원래 PIL 이라는 이름의 도구가 있었고 Pillow 가 그걸 이어받았기 때문이다.
설치 이름과 import 이름이 다른 경우가 종종 있다. pip install pillow 를 했는데 import pillow 가 안 된다고 당황하지 않으면 된다.

 

1. 실습 재료 — 사진도 코드로 만든다

남의 사진을 받아오지 않는다. 큰 사진을 코드로 그린다. 스마트폰 사진 크기(3000×2000)로 만든다.

import os
from PIL import Image, ImageDraw

os.makedirs("사진", exist_ok=True)

# (하늘색, 해 색) 세 벌
scenes = [
    ((70, 130, 180), (240, 220, 120)),
    ((90, 150, 90),  (250, 250, 250)),
    ((160, 90, 110), (255, 200, 90)),
]

for i, (sky, sun) in enumerate(scenes, start=1):
    # "RGB" 는 색 방식, (3000, 2000) 은 가로x세로, 마지막이 배경색
    img = Image.new("RGB", (3000, 2000), sky)

    # ImageDraw 는 그림 위에 도형을 그리는 붓이다
    d = ImageDraw.Draw(img)
    d.ellipse((2300, 200, 2700, 600), fill=sun)                          # 해
    d.polygon([(0, 2000), (900, 900), (1800, 2000)], fill=(60, 90, 60))  # 산
    d.rectangle((0, 1750, 3000, 2000), fill=(80, 70, 55))                # 땅

    # quality 는 JPEG 압축 정도다. 높을수록 선명하고 용량이 크다 (1~95)
    # f"{i:03d}" 는 3 을 003 으로 만든다. 안 그러면 정렬이 1, 10, 2 순서가 된다
    img.save(f"사진/행사_{i:03d}.jpg", quality=92)

print(sorted(os.listdir("사진")))

 

출력결과

ai-course/사진 폴더를 열어 확인해본다. 한 장이 3000×2000 이라 화면에 꽉 찬다.

 

2. 한 장을 열어본다

import glob
from PIL import Image

paths = sorted(glob.glob("사진/*.jpg"))

img = Image.open(paths[0])       # 파일을 여는 것뿐. 아직 아무것도 안 바꿨다

print(img.size)        # (가로, 세로)
print(img.width)
print(img.height)
print(img.format)
print(img.mode)

 

출력결과

 

 

괄호가 없다. img.size 는 함수가 아니라 값이다. 4강에서 본 a.shape 와 같다.

 

3. 한 장을 줄여본다

 

import os
import glob
from PIL import Image

paths = sorted(glob.glob("사진/*.jpg"))
img = Image.open(paths[0])

# thumbnail 은 "이 상자 안에 들어가게" 줄인다. 비율은 알아서 지킨다.
# 800x800 상자에 3000x2000 을 넣으면 800x533 이 된다.
img.thumbnail((800, 800))

img.save("한장_작게.jpg", quality=85)

print(img.size)
print(round(os.path.getsize(paths[0]) / 1024, 1))          # 원본 KB
print(round(os.path.getsize("한장_작게.jpg") / 1024, 1))    # 결과 KB

 

출력결과

 

120KB 가 12KB 가 됐다. 가로는 3.75배 줄었는데 용량은 10배 줄었다. 사진은 넓이로 계산되기 때문이다 — 3000×2000 = 600만 점이 800×533 = 42만 점이 되어 점의 개수가 14배 차이다. 거기에 quality=85 로 압축을 조금 더 준 결과가 10배다.

 

4. 바꾸는 방법은 갈아끼우면 된다

thumbnail 자리에 다른 것을 넣으면 다른 일을 한다. 틀은 그대로다.

 

 

 

표를 자세히 보면 첫 줄만 img = 가 없다. 이게 이 라이브러리에서 가장 자주 걸리는 함정이다.