블로그 사진 편집 자동화: 이미지 리사이징 및 얼굴 가리기

블로그 사진편집 자동화

블로그 사진 편집 자동화(이미지 리사이징 및 얼굴 가리기)

블로그에 사진을 첨부하기 전에 저는 보통 2가지 작업을 합니다.

 

첫번째는 용량을 줄이기 위해 이미지 크기를 축소합니다. 갤럭시 S23울트라의 경우 3000 X 4000 픽셀인데 사이즈를 40% 축소(1200 X 1600)하면 용량이 확연히 줍니다. 이는 용량부담(=돈) 감소와 로딩속도 향상으로 이어져 검색사이트에 좋은 점수를 받는 요인이 됩니다.

 

두번째는 사진 속 사람 얼굴에 스티커를 붙여 가려줍니다. 내 얼굴도 공개하기 싫고 또한 다른 사람 얼굴도 불필요하게 담는것도 좋지 않은것 같아서입니다.

 

이 2가지 작업은 간단하지만 수작업으로 해야하고 꽤 귀찮은 일입니다. 그런데 이러한 작업을 클릭한번으로 자동으로 처리할 수 있는 코드를 소개하고자 합니다.

 

이미지 용량 자동 축소 기능

▷ 이미지 크기를 지정된 비율로 자동 축소하여 파일 용량 감소 ▷ 블로그나 웹사이트 업로드 시 빠른 로딩 속도 확보 및 저장 공간 효율 증대

 

고화질 이미지는 보기에는 좋지만, 웹사이트나 블로그에 업로드할 때 로딩 속도를 느리게 만들고 서버 공간을 많이 차지하는 원인이 됩니다.

 

이 파이썬 코드는 `cv2.resize` 함수를 사용하여 이미지의 가로, 세로 크기를 사용자가 지정한 비율로 줄여줍니다. 예를 들어, `scale_percent=40`으로 설정하면 이미지의 크기가 원래의 40%로 축소되어 파일 용량이 크게 줄어듭니다. 이를 통해 블로그나 웹사이트에 이미지를 더욱 빠르고 효율적으로 게시할 수 있습니다.

정면 및 측면 얼굴 자동 인식 및 스티커 부착 기능

▷ 하르 캐스케이드 분류기를 사용하여 이미지 속 정면 및 측면 얼굴 자동 감지 ▷ 인식된 얼굴 영역에 사용자가 지정한 스티커 이미지 자동 합성 ▷ 여러 장의 사진에 일괄적으로 스티커를 적용하여 편집 시간 단축
이 스크립트의 핵심 기능 중 하나는 사진 속 얼굴을 자동으로 인식하고 스티커를 부착해주는 것입니다. `cv2.CascadeClassifier`를 사용하여 미리 학습된 하르 캐스케이드 XML 파일을 로드하여 이미지에서 얼굴을 찾습니다.

 

특히, 정면 얼굴뿐만 아니라 측면 얼굴까지 인식할 수 있도록 두 개의 캐스케이드 분류기(`haarcascade_frontalface_default.xml`, `haarcascade_profileface.xml`)를 사용한 것이 특징입니다. 얼굴이 감지되면 해당 영역에 `PIL (Python Imaging Library)`을 이용하여 사용자가 지정한 스티커 이미지를 자동으로 합성해줍니다. 여러 장의 사진에 동일한 스티커를 일괄적으로 적용해야 할 때 매우 유용하며, 재미있는 사진 편집을 손쉽게 만들 수 있도록 도와줍니다.

 

간단한 사용 방법

▷ `raw_img` 폴더에 원본 이미지 파일을 저장 ▷ `smile.png` 파일을 스티커 이미지로 준비 ▷ `process_images` 함수 호출 시 원본 폴더, 결과 폴더, 스티커 파일 경로를 지정 ▷ 실행 후 `pre_img` 폴더에서 처리된 이미지 확인
위 파이썬 코드를 사용하는 방법은 매우 간단합니다. 먼저 편집하고자 하는 원본 이미지 파일들을 `raw_img`라는 폴더에 넣어주세요. 그리고 얼굴에 붙일 스티커 이미지 (예: `smile.png`) 파일을 준비합니다. 스크립트 내의 `process_images` 함수를 호출할 때, 원본 이미지 폴더 경로 (`folder_path`), 결과 이미지를 저장할 폴더 경로 (`output_folder`), 그리고 스티커 이미지 파일 경로 (`sticker_path`)를 적절하게 설정해주면 됩니다. 스크립트를 실행하면, 원본 이미지들이 자동으로 리사이징되고 얼굴이 인식되어 스티커가 부착된 후 `pre_img` 폴더에 저장됩니다.

 

Python
import cv2
import os
from PIL import Image

# 하르 캐스케이드 파일 경로
face_cascade_front = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
face_cascade_side = cv2.CascadeClassifier('haarcascade_profileface.xml')

def process_images(folder_path, output_folder, sticker_path, scale_percent=40):
    """
    폴더 내 이미지 파일의 크기를 축소하고 얼굴(정면, 측면)에 스티커를 추가합니다.

    Args:
        folder_path (str): 이미지 파일이 있는 폴더 경로
        output_folder (str): 처리된 이미지를 저장할 폴더 경로
        sticker_path (str): 스마일 스티커 이미지 파일 경로
        scale_percent (int, optional): 이미지 축소 비율 (기본값: 40)
    """

    # 스티커 이미지 로드
    sticker = Image.open(sticker_path)

    # 출력 폴더 생성 (없을 경우)
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    # 폴더 내 모든 이미지 파일 처리
    for filename in os.listdir(folder_path):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            image_path = os.path.join(folder_path, filename)
            image = cv2.imread(image_path)

            if image is None:
                print(f"이미지 로드 실패: {image_path}")
                continue

            # 이미지 크기 축소
            width = int(image.shape[1] * scale_percent / 100)
            height = int(image.shape[0] * scale_percent / 100)
            dim = (width, height)
            resized_image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)

            # 얼굴 인식 (정면 및 측면)
            gray = cv2.cvtColor(resized_image, cv2.COLOR_BGR2GRAY)
            faces_front = face_cascade_front.detectMultiScale(gray, 1.3, 5)
            faces_side = face_cascade_side.detectMultiScale(gray, 1.3, 5) # 측면 얼굴 인식

            # 얼굴에 스티커 추가
            pil_image = Image.fromarray(cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB))
            for (x, y, w, h) in faces_front:
                resized_sticker = sticker.resize((w, h))
                pil_image.paste(resized_sticker, (x, y), resized_sticker)
            for (x, y, w, h) in faces_side: # 측면 얼굴 스티커 추가
                resized_sticker = sticker.resize((w, h))
                pil_image.paste(resized_sticker, (x, y), resized_sticker)

            # 처리된 이미지 저장
            output_path = os.path.join(output_folder, filename)
            pil_image.save(output_path)

            print(f"처리 완료: {output_path}")

# 사용 예시
folder_path = "raw_img"
output_folder = "pre_img"
sticker_path = "smile.png"

process_images(folder_path, output_folder, sticker_path)