콘텐츠로 이동

이미지 처리 실전 팁

블로그, 콘텐츠 작업에서 자주 쓰는 이미지 처리 노하우 모음.


1. 얼굴 블러 처리 (YuNet)

여행 사진에서 타인 얼굴을 블러 처리할 때 쓰는 방법.

모델 비교 (2026-04-18 테스트 완료)

모델 설치 정면 옆모습 선글라스 작은 얼굴 오탐
Haar Cascade opencv 내장 O X X X 많음 (기와, 몸통)
MediaPipe pip install O X X X 적음 (못 잡는 게 문제)
OpenCV DNN (SSD) opencv 내장 O X X X 적음 (못 잡는 게 문제)
YuNet opencv 4.x 내장 O O O O 거의 없음

결론: YuNet이 압도적으로 좋다. 별도 pip 설치 없이 OpenCV만 있으면 됨.

사용법

import cv2

# 모델 로드 (최초 1회 다운로드 필요)
# https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx
model_path = "face_detection_yunet_2023mar.onnx"

# 이미지 읽기
img = cv2.imread("photo.jpg")
h, w = img.shape[:2]

# 감지기 생성
detector = cv2.FaceDetectorYN.create(model_path, '', (w, h), 0.5, 0.3, 5000)
#                                                        신뢰도  NMS   최대감지수

# 감지
_, faces = detector.detect(img)

# 블러 처리
if faces is not None:
    for face in faces:
        x, y, fw, fh = int(face[0]), int(face[1]), int(face[2]), int(face[3])
        pad = int(fw * 0.2)  # 여유 패딩
        x1, y1 = max(0, x - pad), max(0, y - pad)
        x2, y2 = min(w, x + fw + pad), min(h, y + fh + pad)
        region = img[y1:y2, x1:x2]
        blurred = cv2.GaussianBlur(region, (99, 99), 30)
        img[y1:y2, x1:x2] = blurred

cv2.imwrite("photo_blurred.jpg", img)

주의사항

  • 모델 파일 경로에 한글 있으면 안 됨 - cv2가 한글 경로의 ONNX 파일을 못 읽음. 영문 경로에 배치할 것
  • 한글 경로의 이미지 읽기 - cv2.imread()도 한글 경로 못 읽음. numpy + imdecode 우회:
    import numpy as np
    with open("한글경로/사진.jpg", 'rb') as f:
        data = np.frombuffer(f.read(), dtype=np.uint8)
    img = cv2.imdecode(data, cv2.IMREAD_COLOR)
    
  • 연등, 풍선 등 둥근 물체 오탐 가능 - 결과물 반드시 눈으로 확인
  • 오탐 시 해당 사진만 원본에서 블러 없이 복원 (뒷모습만 있는 사진 등)
  • 신뢰도 조절: 기본 0.5, 낮추면(0.3) 더 많이 잡지만 오탐도 증가

현재 모델 파일 위치

D:\claude-blog\face_detection_yunet_2023mar.onnx

다른 프로젝트에서도 이 파일 경로 참조하면 됨.


2. EXIF 회전 처리

스마트폰 세로 사진은 EXIF 메타데이터에 회전 정보가 저장됨. PIL은 이걸 무시하고 원본대로 읽어서 세로 사진이 가로로 뒤집혀 보임.

from PIL import Image, ImageOps

img = Image.open("photo.jpg")
img = ImageOps.exif_transpose(img)  # 이거 한 줄이면 됨
img.save("photo_fixed.jpg", quality=90)

반드시 모든 사진에 적용. 안 하면 블로그에 가로로 올라감.


3. 세로 사진 리사이즈

세로 사진은 가로 600px로 리사이즈 (모바일 가독성).

w, h = img.size
if h > w and w > 600:  # 세로 사진 + 600px 초과
    ratio = 600 / w
    img = img.resize((600, int(h * ratio)), Image.LANCZOS)

4. SEO 파일명

원본 20260417_102937.jpgseokguram-bell-pavilion-cherry-blossom.jpg

규칙: - 영문 소문자 - 하이픈(-) 구분 - 장소 + 대상 키워드 포함 - alt 텍스트도 함께 매핑 (alt_map.json)


5. 전체 워크플로우 (여행 사진 → 블로그)

1. 사진 폴더에서 후보 전체 확인 (Read로 하나씩)
2. 블로그 섹션별 셀렉 (12~20장)
3. SEO 파일명 + alt 텍스트 매핑
4. EXIF 회전 + 세로 리사이즈 + YuNet 블러 일괄 처리
5. 결과물 눈으로 확인 (오탐/미탐 체크)
6. 문제 사진만 수동 보정 또는 원본 복원
7. upload.py로 티스토리 업로드

참고 스크립트: D:\claude-blog\260418 경주 석굴암\blur_yunet.py