IT/개발

구글 mediapipe API를 이용하여 얼굴 인식 및 face landmark 그리기

빗자루검 2025. 7. 16. 17:30
반응형

1. mediapipe 개요 

 

https://mediapipe-studio.webapps.google.com/home

 

 

Mediapipe 패키지는 Google에서 개발한 오픈소스 프레임워크로, 주로 기계 학습 모델을 활용한 멀티모달(다중 모드) 지각 인식을 위한 솔루션을 제공합니다. 즉, 이미지, 비디오, 오디오 등의 다양한 데이터를 입력으로 받아 사람의 얼굴, 손, 몸 등의 특징을 실시간으로 감지하고 추적하는 데 특화되어 있습니다.

 

 

  • 실시간 처리: 매우 낮은 지연 시간으로 작동하도록 설계되어 실시간 애플리케이션에 적합합니다. 웹캠 피드, 스마트폰 카메라 등에서 직접 데이터를 처리할 수 있습니다.
  • 크로스 플랫폼 지원: 데스크톱(Linux, macOS, Windows), 모바일(Android, iOS), 웹 등 다양한 플랫폼에서 사용할 수 있도록 지원합니다.
  • 다양한 솔루션 제공: 얼굴 감지, 얼굴 랜드마크, 손 랜드마크, 자세 추정, 객체 감지 등 다양한 사전 훈련된 솔루션을 제공하여 개발자가 복잡한 모델을 직접 구축할 필요 없이 쉽게 활용할 수 있습니다.
  • 그래프 기반 아키텍처: 데이터를 처리하는 파이프라인을 그래프 형태로 구성하여 유연하고 확장 가능한 솔루션 개발을 가능하게 합니다.
  • 경량화된 모델: 모바일 및 임베디드 장치에서도 효율적으로 작동하도록 최적화된 경량화된 모델을 사용합니다.

 

2. 주요 솔루션 

Mediapipe는 다양한 사전 구축된 솔루션을 제공하며, 대표적인 몇 가지는 다음과 같습니다.

  • MediaPipe Face Detection (얼굴 감지): 이미지나 비디오에서 얼굴의 위치를 감지합니다.
  • MediaPipe Face Mesh (얼굴 메시): 468개의 3D 얼굴 랜드마크를 감지하여 얼굴 표정, 움직임 등을 정밀하게 추적합니다. AR(증강 현실) 필터나 가상 메이크업 등에 활용될 수 있습니다.
  • MediaPipe Hands (손 랜드마크): 손의 21개 3D 랜드마크를 감지하여 손가락 움직임, 제스처 등을 인식하는 데 사용됩니다. 가상 현실 상호작용, 수화 인식 등에 활용될 수 있습니다.
  • MediaPipe Pose (자세 추정): 사람의 몸에서 33개의 3D 랜드마크를 감지하여 전신 자세를 추정합니다. 피트니스 트래킹, 재활 치료, 동작 분석 등에 활용될 수 있습니다.
  • MediaPipe Holistic (홀리스틱): 얼굴, 손, 자세 랜드마크를 동시에 감지하여 전반적인 사람의 행동 및 상호작용을 이해하는 데 도움을 줍니다.
  • MediaPipe Objectron (객체 감지): 3D 객체를 감지하고 그 포즈를 추정합니다. 일상적인 물체의 크기, 방향 등을 파악하는 데 사용됩니다.
  • MediaPipe Selfie Segmentation (셀카 분할): 이미지에서 사람과 배경을 분리하여 셀카 애플리케이션에서 배경 변경 등의 기능을 구현할 수 있도록 합니다.

예전에는 여러 모델을 구축하여 각각 전처리 후처리를 통해 만드는 수고가 있었는데 정형화된 비젼 기능은 그냥 가져다가 쓰기만 하면 되는것이 아주 편리합니다. 

 

 

3. mediapipe를 이용한 얼굴인식과 페이스랜드마크 그리기 

 

여기서는 streamlit을 이용하여 파일을 업로드 하고 해당 파일에서 얼굴을 찾고 페이스랜드마크를 순서대로 그려 보겠습니다. 

 


import streamlit as st  # streamlit 라이브러리 임포트(웹앱 UI용)
from PIL import Image, ImageDraw  # PIL 라이브러리에서 이미지 처리 및 그리기 기능 임포트
import numpy as np  # numpy 라이브러리 임포트(배열 및 수치 연산용)

# mediapipe는 pip install mediapipe로 설치 필요
import mediapipe as mp  # mediapipe 라이브러리 임포트(얼굴 검출 및 랜드마크용)

mp_face_detection = mp.solutions.face_detection  # mediapipe의 얼굴 검출 모듈 할당
mp_face_mesh = mp.solutions.face_mesh  # mediapipe의 얼굴 랜드마크(메쉬) 모듈 할당

# 각 기능별 샘플 함수 예시
def detect_face(image_np):  # 얼굴 검출 함수 정의
    with mp_face_detection.FaceDetection(model_selection=1, min_detection_confidence=0.5) as face_detection:  # 얼굴 검출기 초기화
        results = face_detection.process(image_np)  # 이미지에서 얼굴 검출 수행
        return results  # 결과 반환

def detect_face_mesh(image_np):  # 얼굴 랜드마크 검출 함수 정의
    with mp_face_mesh.FaceMesh(static_image_mode=True, max_num_faces=5, refine_landmarks=True) as face_mesh:  # 얼굴 메쉬 검출기 초기화
        results = face_mesh.process(image_np)  # 이미지에서 얼굴 랜드마크 검출 수행
        return results  # 결과 반환

st.title("사진 업로드 및 얼굴 랜드마크 오버레이 웹앱")  # 웹앱 타이틀 표시

uploaded_file = st.file_uploader("사진을 업로드하세요", type=["jpg", "jpeg", "png"])  # 파일 업로더 위젯 생성(이미지 파일만 허용)

if uploaded_file is not None:  # 파일이 업로드된 경우
    image = Image.open(uploaded_file).convert("RGB")  # 업로드된 이미지를 열고 RGB로 변환
    st.subheader("원본 사진")  # 원본 사진 섹션 제목 표시
    st.image(image, caption='업로드한 사진', use_container_width=True)  # 업로드한 이미지 표시

    # 얼굴 검출
    face_results = detect_face(np.array(image))  # 얼굴 검출 함수 호출(이미지를 numpy 배열로 변환)
    overlay_img_face = image.copy()  # 얼굴 박스를 그릴 이미지 복사본 생성
    if face_results.detections:  # 얼굴이 검출된 경우
        draw = ImageDraw.Draw(overlay_img_face)  # 이미지에 그리기 위한 객체 생성
        for detection in face_results.detections:  # 검출된 얼굴마다 반복
            bboxC = detection.location_data.relative_bounding_box  # 얼굴의 상대적 바운딩 박스 정보 추출
            x1 = int(bboxC.xmin * image.width)  # 바운딩 박스 좌상단 x좌표 계산
            y1 = int(bboxC.ymin * image.height)  # 바운딩 박스 좌상단 y좌표 계산
            x2 = int((bboxC.xmin + bboxC.width) * image.width)  # 바운딩 박스 우하단 x좌표 계산
            y2 = int((bboxC.ymin + bboxC.height) * image.height)  # 바운딩 박스 우하단 y좌표 계산
            draw.rectangle([x1, y1, x2, y2], outline=(255,0,0), width=2)  # 얼굴 위치에 빨간색 사각형 그리기
        st.subheader("얼굴 검출 결과")  # 얼굴 검출 결과 섹션 제목 표시
        st.image(overlay_img_face, caption='얼굴이 표시된 사진', use_container_width=True)  # 얼굴 박스가 표시된 이미지 출력
    else:  # 얼굴이 검출되지 않은 경우
        st.warning("얼굴을 찾을 수 없습니다. 다른 사진을 시도해보세요.")  # 경고 메시지 표시

    # 얼굴 랜드마크 검출
    face_mesh_results = detect_face_mesh(np.array(image))  # 얼굴 랜드마크 검출 함수 호출
    overlay_img_mesh = image.copy()  # 랜드마크를 그릴 이미지 복사본 생성
    if face_mesh_results.multi_face_landmarks:  # 얼굴 랜드마크가 검출된 경우
        draw = ImageDraw.Draw(overlay_img_mesh)  # 이미지에 그리기 위한 객체 생성
        for face_landmarks in face_mesh_results.multi_face_landmarks:  # 검출된 얼굴마다 반복
            for lm in face_landmarks.landmark:  # 각 얼굴의 랜드마크 포인트마다 반복
                x = int(lm.x * image.width)  # 랜드마크 x좌표 계산
                y = int(lm.y * image.height)  # 랜드마크 y좌표 계산
                draw.ellipse((x-1, y-1, x+1, y+1), fill=(0,255,0))  # 해당 위치에 초록색 점(원) 그리기
        st.subheader("얼굴 랜드마크 오버레이")  # 얼굴 랜드마크 오버레이 섹션 제목 표시
        st.image(overlay_img_mesh, caption='랜드마크가 표시된 사진', use_container_width=True)  # 랜드마크가 표시된 이미지 출력
    else:  # 얼굴 랜드마크가 검출되지 않은 경우
        st.warning("얼굴 랜드마크를 찾을 수 없습니다.")  # 경고 메시지 표시

 

 

4. 결과 확인 

 

 

 

 

 

반응형