강의를 마무리하는 시점에서 첨언을 드리자면, 이거는 AI아바타를 만든다기보다 그냥 이미지 여러개를 번갈아 돌리면서 TTS로 생성된 음성파일을 들려주는 수준의 강좌입니다. 뭔가 입모양이 움직이고 3D로 새로운 얼굴의 아바타가 생성되는 그런 마법같은 일은 생기지 않습니다. 강의 마지막부분에서 결과물에 상당히 실망할수도 있음을 미리 알려드립니다. 그래도 문자열을 음성으로 변환하거나, 이미지에서 얼굴부분만 가져오는 라이브러리등은 알아두면 좋을것 같아요.
안녕하세요. 얼마전 Synthesia라는 AI동영상 생성툴을 발견해서 테스트해보던중에 AI아바타를 만들수 있지는 않을까 하는 호기심에 찾아봤는데 Creating an AI Avatar라는 아티클을 발견해서 함께 시도해보면 어떨까 싶어서 강좌를 시작합니다. 저는 AI나 머신러닝등에는 지식이 전무해서 따라하면서도 설명이 살짝 부족할 수도 있어요. 그래도 코드를 보면서 최대한 열심히 설명을 해보도록하겠습니다.
이번시간에는 Python을 이용하여, 여러개의 이미지 속에서 얼굴만 모아서 하나의 이미지에 나란히 붙이는 코딩을 해보도록 하겠습니다. 아래와 같이 코딩에 필요한 라이브러리를 설치해주세요.
pip install numpy dlib opencv-python pillow
collect_faces.py라는 파일을 하나 생성합니다. 여기에서 사용한 라이브러리는 opencv-python의 cv2, dlib, pillow의 Image, 그리고 numpy입니다. 필요한 라이브러리를 코드에 포함시켜주세요.
import cv2
import dlib
from PIL import Image
import numpy as np
그리고 얼굴이 들어있는 이미지 3개를 준비해서 같은 폴더에 저장해주시고 해당 이미지명들을 배열안에 넣어서 아래와 같이 변수에 저장해주세요.
image_paths = ['image1.png' , 'image2.png' , 'image3.png']
이미지에서 얼굴을 추출해서 반환하는 함수를 만들겠습니다. 일단 함수 안에서 사용할 얼굴인식 모듈은 코드가 무거우니까 함수 윗쪽에 한개만 선언해놓고 함수 안에서 계속 갖다 쓰는걸로 할게요. 인자로 이미지경로를 받고 cv2라이브러리로 해당이미지를 읽어서 dlib라이브러리가 제공하는 얼굴 검출 기능을 사용하여 이미지 안의 얼굴들을 떠냅니다. 이미지 안에 얼굴이 1개 이상 있는 경우를 생각해서 첫번째 얼굴을 반환하는걸로 할게요. 이때 검출한 얼굴 이미지는 칼라포멧이 BGR포멧입니다. cv2.cvtColor()함수에 변환필터 cv2.COLOR_BGR2RGB를 명시해서 BGR을 RGB포멧으로 변환해서 반환하도록 할게요.
detector = dlib.get_frontal_face_detector()
def extract_face (image_path):
image = cv2.imread(image_path)
faces = detector(image)
if len (faces) > 0 :
face = faces[ 0 ] # 발견된 첫 번째 얼굴 추출
x, y, w, h = face.left(), face.top(), face.width(), face.height()
face_image = image[y:y+h, x:x+w]
return cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB)
else :
return None
이제 생성한 함수를 호출하여 이미지 안의 얼굴들을 모아볼게요. 함수에서 반환받은 얼굴들을 모아 저장할 배열 faces를 하나 정의합니다. 그리고 이미지들을 돌면서 방금만든 extract_face()함수에 이미지경로를 넘겨주어 호출합니다. face가 null이 아니면 faces 배열에 넘겨받은 얼굴을 추가합니다.
faces = []
for path in image_paths:
face = extract_face(path)
if face is not None :
faces.append(face)
이번에는 배열에 모은 얼굴들을 하나로 합성해서 새로운 얼굴을 만들어 볼게요. numpy의 hstack()함수에 얼굴배열을 넘겨주어 하나로 통합하는 코드입니다.
if faces:
composite_face = np.hstack(faces)
composite_image = Image.fromarray(composite_face)
composite_image.save('composite_faces.jpg')
composite_image.show()
else :
print ( "이미지에서 얼굴이 감지되지 않았습니다." )
아래는 완성된 코드입니다.
import cv2
import dlib
from PIL import Image
import numpy as np
# dlib 얼굴 검출기 로드
detector = dlib.get_frontal_face_detector()
# 이미지에서 얼굴을 추출하는 함수
def extract_face(image_path):
image = cv2.imread(image_path)
faces = detector(image)
if len(faces) > 0:
face = faces[0] # 발견된 첫 번째 얼굴 추출
x, y, w, h = face.left(), face.top(), face.width(), face.height()
face_image = image[y:y+h, x:x+w]
return cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB)
else :
return None
# 이미지 경로
image_paths = ['image1.png', 'image2.png', 'image3.png']
# 얼굴을 추출하여 저장
faces = []
for path in image_paths:
face = extract_face(path)
if face is not None :
faces.append(face)
# 얼굴을 수평으로 쌓아 합성 이미지 생성
if faces:
composite_face = np.hstack(faces)
composite_image = Image.fromarray(composite_face)
composite_image.save('composite_faces.jpg')
composite_image.show()
else :
print ( "이미지에서 얼굴이 감지되지 않았습니다." )
그럼 코드를 실행해볼게요.
저는 이미지 3개를 다음과 같이 준비했습니다.

위의 이미지를 실행파일과 같은 폴더에 저장하고 스크립트를 실행해 볼게요.
python collect_faces.py
결과는 다음과 같이 얼굴만 같은 크기로 모아서 하나의 이미지에 나란히 붙여줍니다.
