세로 또는 가로로 긴 이미지의 썸네일 문제점
사진 업로드, 그리고 자동으로 생성된 썸네일. 편리하다고 생각했던 이 기능에도 숨겨진 고충이 있었습니다. "왜 얼굴이 짤렸을까?", "이 부분만 보여주면 좋았을텐데..." 자동 생성된 썸네일에 대한 아쉬움이 한두번이 아니었습니다.
얼굴 인식의 힘을 빌려 이 문제를 해결하려고 합니다. 이 포스트에서는 얼굴 인식 기술을 활용해 짤리지 않는, 사용자의 얼굴을 중심으로 한 완벽한 1:1 썸네일을 만드는 방법을 함께 알아보겠습니다.
먼저 작업의 완성된 결과물 부터 보겠습니다.
원본 이미지 | 생성된 썸네일 |
|
주어진 이미지에서 얼굴 인식을 활용하여 이미지 상단에 얼굴이 위치하도록 1:1 비율의 썸네일을 만들어보겠습니다.
관련 코드 입니다.
import cv2
import os
import numpy as np
class ThumbnailCreator:
def __init__(self):
# OpenCV를 사용하여 얼굴 인식을 위한 준비
self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
def create_square_thumbnail(self, image, save_folder, image_name):
"""
주어진 이미지를 바탕으로 1:1 비율의 썸네일 이미지를 생성하고 저장 후, 저장 경로를 반환합니다.
얼굴 인식을 통해 얼굴이 이미지 상단에 위치하도록 조절합니다.
:param image: PIL 이미지 객체
:param save_folder: 저장할 폴더 경로
:param image_name: 이미지 파일명
:return: 저장된 썸네일 이미지의 경로
"""
face_position = self._detect_face(image)
thumbnail = self._create_thumbnail_based_on_face(image, face_position)
return self._save_thumbnail(thumbnail, save_folder, image_name)
def _detect_face(self, image):
"""
이미지 내의 얼굴을 인식하는 함수
:param image: PIL 이미지 객체
:return: 얼굴의 위치와 크기 (x, y, w, h) 또는 None (얼굴 미검출시)
"""
gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY)
faces = self.face_cascade.detectMultiScale(gray, 1.3, 5)
return faces[0] if len(faces) > 0 else None
def _create_thumbnail_based_on_face(self, image, face_position):
"""
얼굴의 위치를 바탕으로 이미지를 1:1 비율로 잘라내는 함수
:param image: PIL 이미지 객체
:param face_position: 얼굴의 위치와 크기 (x, y, w, h) 또는 None
:return: 1:1 비율로 잘린 썸네일 이미지
"""
width, height = image.size
if face_position:
x, y, w, h = face_position
offset_y = h // 3
else:
x = width // 2
y = height // 2
offset_y = 0
if width == height:
return image
elif width < height:
return self._crop_vertical_image(image, y, offset_y)
else:
return self._crop_horizontal_image(image, x, w)
def _crop_vertical_image(self, image, y, offset_y):
"""
세로 이미지를 적절한 위치에서 1:1 비율로 잘라내는 함수
:param image: PIL 이미지 객체
:param y: 얼굴의 y 좌표
:param offset_y: 얼굴을 상단으로 올리기 위한 오프셋
:return: 1:1 비율로 잘린 썸네일 이미지
"""
width, height = image.size
new_height = width
top = max(0, y - offset_y)
bottom = top + new_height
if bottom > height:
bottom = height
top = height - new_height
return image.crop((0, top, width, bottom))
def _crop_horizontal_image(self, image, x, w):
"""
가로 이미지를 적절한 위치에서 1:1 비율로 잘라내는 함수
:param image: PIL 이미지 객체
:param x: 얼굴의 x 좌표
:param w: 얼굴의 너비
:return: 1:1 비율로 잘린 썸네일 이미지
"""
width, height = image.size
new_width = height
left = max(0, x + w // 2 - new_width // 2)
right = left + new_width
if right > width:
right = width
left = width - new_width
return image.crop((left, 0, right, height))
def _save_thumbnail(self, thumbnail, save_folder, image_name):
"""
썸네일 이미지를 저장하고 저장 경로를 반환하는 함수
:param thumbnail: PIL 썸네일 이미지 객체
:param save_folder: 저장할 폴더 경로
:param image_name: 이미지 파일명
:return: 저장된 썸네일 이미지의 경로
"""
thumbnail_np = cv2.cvtColor(np.array(thumbnail), cv2.COLOR_RGB2BGR)
thumbnail_np = cv2.resize(thumbnail_np, (300, 300), interpolation=cv2.INTER_AREA)
thumbnail_path = os.path.join(save_folder, f'thumbnail_{image_name}')
cv2.imwrite(thumbnail_path, thumbnail_np)
return thumbnail_path
ThumbnailCreator 클래스
우선 전체적인 구조로 ThumbnailCreator 클래스를 생성하였습니다. 이 클래스는 주어진 이미지를 바탕으로 1:1 비율의 썸네일 이미지를 생성하는 기능을 담당합니다.
- __init__ 메소드: OpenCV의 얼굴 인식 기능을 초기화하는 부분입니다.
- create_square_thumbnail: 외부에서 호출되는 주요 함수로, 이미지를 입력받아 썸네일을 생성하며, 생성된 썸네일 이미지의 저장 경로를 반환합니다.
- _detect_face: 이미지 내의 얼굴 위치와 크기를 반환하는 함수입니다. 얼굴이 없는 경우 None을 반환합니다.
- _create_thumbnail_based_on_face: 얼굴의 위치를 기준으로 이미지를 1:1 비율로 잘라내는 작업을 수행합니다.
- _crop_vertical_image와 _crop_horizontal_image: 세로 또는 가로 이미지를 적절한 위치에서 잘라내는 함수입니다.
- _save_thumbnail: 생성된 썸네일 이미지를 저장하고, 저장된 경로를 반환합니다.
사용 방법
- ThumbnailCreator 클래스를 초기화합니다.
- create_square_thumbnail 메소드를 호출하여 이미지를 입력받고, 썸네일을 생성합니다.
예시:
thumbnail_creator = ThumbnailCreator()
thumbnail_path = thumbnail_creator.create_square_thumbnail(image, './save_folder/', 'sample_image.jpg')
print(f"생성된 썸네일 경로: {thumbnail_path}")
이 클래스를 활용하면 손쉽게 얼굴 인식을 통한 1:1 비율의 썸네일을 생성할 수 있습니다. 특히 얼굴 위치를 기준으로 썸네일을 생성함으로써 사용자가 중요하게 여기는 정보를 잃지 않고, 썸네일 이미지를 표현할 수 있습니다.
이렇게 주어진 이미지를 바탕으로 얼굴을 인식하여 1:1 비율의 썸네일을 생성완료 하였습니다.
세로 또는 가로로 긴 이미지들을 자동화하여 썸네일을 만들일이 있었는데 이 로직으로 많은 썸네일을 효율적으로 만들수 있게 되었습니다.
'개발 공부 기록하기 > - Python' 카테고리의 다른 글
ChatGPT와 함께 Android strings.xml 자동번역 및 추가 10초만에 하기 (0) | 2023.08.22 |
---|