MediaPipe Face Landmarker — 학부생을 위한 학습 교재

05. 기존 Face Mesh와의 차이 — 레거시에서 무엇이 달라졌나

목차

04장에서 본 신규 출력 둘은 52 블렌드셰이프 계수와 4×4 변환행렬이다. 둘 다 레거시 Face Mesh에는 없던 출력이다. 이 장은 그 차이를 정면으로 비교한다.

478 토폴로지 상세는 03장, 블렌드셰이프 내부는 04장에서 다뤘다. 여기서는 "Face Mesh엔 없고 Landmarker엔 있다" 수준으로만 짚는다.

5.1 서두 요약 — 한눈에

레거시 Face Mesh에서 현행 Face Landmarker로 옮길 때 달라지는 것은 크게 다섯 갈래다.

  • 정체성. Face Mesh는 레거시 MediaPipe Solutions의 솔루션이다(mp.solutions.face_mesh.FaceMesh). Face Landmarker는 새 MediaPipe Tasks API의 비전 태스크다(mp.tasks.vision.FaceLandmarker). Google은 2023년 3월 1일자로 레거시 Solutions 지원을 종료했다. 후속이 Tasks API다.
  • 출력. 둘 다 478 랜드마크까지 낼 수 있다. Face Landmarker는 여기에 더해 52개 blendshape 계수와 4×4 변환행렬을 옵션으로 함께 낸다. 이 두 출력은 레거시 Face Mesh의 표준 출력에 없다. 가장 중요한 차이다.
  • 모델 제공. Face Mesh는 라이브러리에 내장된 계산 그래프(binarypb)를 쓴다. Face Landmarker는 .task 모델 번들 파일을 base_options로 외부에서 넣어 준다.
  • 실행 모드. Face Mesh는 static_image_mode(불리언) 하나로 이미지와 스트림을 구분했다. Face Landmarker는 IMAGE / VIDEO / LIVE_STREAM 세 가지 running_mode를 명시한다. LIVE_STREAM은 비동기 콜백으로 결과를 받는다.
  • 플랫폼. Tasks API는 Android, iOS, Web(JS), Python에서 같은 개념·옵션 이름을 쓴다. 레거시는 플랫폼별 제공 형태가 흩어져 있었다.
광고 · Advertisements

5.2 두 API의 정체성 — 같은 일, 다른 세대

두 API가 하는 핵심 작업은 같다. 얼굴을 찾고, 그 위에 조밀한 3D 얼굴 랜드마크(face mesh)를 회귀로 얹는다. 다른 것은 "어느 세대의 프레임워크에 속하느냐"다.

구분 Face Mesh Face Landmarker
소속 프레임워크 MediaPipe (Legacy) Solutions MediaPipe Tasks API (= 신 MediaPipe Solutions)
Python 진입점 mp.solutions.face_mesh.FaceMesh mp.tasks.vision.FaceLandmarker
JS 패키지 @mediapipe/face_mesh @mediapipe/tasks-vision
상태 지원 종료(2023-03-01), as-is 제공 현행 권장

혼동 주의 1 — 이름이 헷갈리는 이유. 레거시 솔루션 이름이 "Face Mesh"였다. 새 태스크 이름은 "Face Landmarker"다. 그런데 새 태스크가 안에서 쓰는 모델 중 하나도 이름이 "face mesh model"이다(5.3절). 즉 Face Mesh는 옛 솔루션 이름이면서, 동시에 Face Landmarker 번들 안의 한 모델 이름이기도 하다. 같은 단어지만 가리키는 층위가 다르다.

혼동 주의 2 — JS 패키지로 구별하기. 웹 튜토리얼이 @mediapipe/face_mesh를 import하면 레거시다. @mediapipe/tasks-vision을 import하면 신 API다. 2023년 이전 튜토리얼의 옛 CDN 경로는 deprecated 모델을 가리킨다.

왜 옮겼나. 레거시 Solutions는 솔루션마다 API 형태와 모델 패키징, 플랫폼 지원이 제각각이었다. 같은 "얼굴 랜드마크"라도 Python과 Web, Android의 사용법과 출력 구조가 서로 달랐다. 새 Tasks API는 이를 하나의 패턴으로 다시 설계했다. BaseOptions(.task 번들)로 모델을 넣고, Options로 실행 모드·임계값·출력 옵션을 정하고, detect/detectForVideo/detectAsync로 부른다. 그래서 플랫폼이 달라도 사용법이 같아지고, 모델 파일을 갈아끼우기 쉬워졌다(01장).

5.3 .task 번들이 품은 모델들

Face Landmarker의 face_landmarker.task 번들은 세 개의 모델을 담는다. "얼굴 검출 → 메시 회귀 → 표정 회귀"가 한 파일 안에 들어 있다(02장).

번들 내 모델 역할 입력 해상도(공식 명시)
Face detection model 얼굴 검출 (BlazeFace short-range 계열) 192 × 192
Face mesh model 얼굴 표면 전체에 랜드마크 매핑 256 × 256
Blendshape prediction model 표정(blendshape) 계수 예측 1 × 146 × 2 (랜드마크 부분집합 입력)

레거시 Face Mesh도 안에서 "검출 → 랜드마크 회귀"를 했다(그래프 face_landmark_front_cpu.binarypb). 다만 세 번째 모델, 곧 blendshape 예측 모델이 번들에도 그래프에도 없었다. 이 세 번째 모델이 있느냐 없느냐가 그대로 출력 차이로 이어진다(5.4절).

아래 그림은 두 세대의 내부 경로를 나란히 둔 것이다.

Face Landmarker (Tasks API)

subset

Face detector model 192x192

Face mesh model 256x256

face_landmarks 478

Blendshape model 1x146x2

face_blendshapes 52

facial_transformation_matrixes 4x4

Legacy Face Mesh (Solutions)

Face detector (BlazeFace)

Mesh regressor 468/478

multi_face_landmarks

점선 경로(blendshape)와 facial_transformation_matrixes는 신 API에만 있다. 레거시 경로는 랜드마크에서 끝난다.

5.4 출력(output) 차이 — 가장 중요한 차이

한눈 비교표

출력 항목 Face Mesh (Legacy) Face Landmarker (Tasks)
얼굴 랜드마크 468 기본 / refine_landmarks=True 시 478(iris 포함) 478 (3D, 정규화 x·y, 상대 z)
다중 얼굴 컨테이너 multi_face_landmarks (리스트) face_landmarks (리스트)
Blendshape 계수(52) 없음 face_blendshapes (옵션 output_face_blendshapes=True)
Facial transformation matrix(4×4) 없음(표준 출력 아님) facial_transformation_matrixes (옵션 output_facial_transformation_matrixes=True)
좌표 정규화 이미지 폭·높이로 0~1 정규화된 x,y, 상대 깊이 z 동일 규약(정규화 x·y, 상대 z)

코드 근거: 레거시 소스에 FACEMESH_NUM_LANDMARKS = 468FACEMESH_NUM_LANDMARKS_WITH_IRISES = 478 상수가 있고, 출력 필드는 multi_face_landmarks다. 신 API의 FaceLandmarkerResultface_landmarks, face_blendshapes, facial_transformation_matrixes 세 필드를 갖는다.

신규 출력 ① — 52 blendshapes

무엇인가. 눈을 깜빡이고(eyeBlinkLeft), 눈썹을 올리고(browInnerUp), 입을 벌리는 식으로, 얼굴 표정의 정도를 0~1 계수 52개로 표현한 것이다. ARKit 52 표준과 맞춰져 있다.

차이의 본질은 이렇다. Face Mesh는 점(landmark)의 위치만 준다. "지금 웃고 있나?"를 알려면 사용자가 직접 입꼬리 좌표로 규칙을 짜야 했다. Face Landmarker는 표정 자체를 회귀해 계수로 바로 준다. 별도의 blendshape 모델(1×146×2 입력) 덕분이다. 카테고리와 회귀 메커니즘 상세는 04장에서 다뤘다.

cheekPuff 각주. 04장에서 본 cheekPuff 같은 일부 이름은 모델카드가 학습 부산물로 표기한 것이다. 런타임에서 실제로 나오는 52 계수는 Blendshape V2 모델 기준이다. 그러니 "모델카드에 적힌 이름 목록"과 "런타임 52 출력"을 같은 것으로 섞어 읽지 않는다(상세는 04장).

신규 출력 ② — 4×4 facial transformation matrix

무엇인가. canonical face model(표준 정면 3D 얼굴)을 지금 검출된 얼굴의 위치·회전·크기로 옮기는 4×4 강체 변환 행렬이다. uniform scale과 rotation, translation을 담는다. 컬럼-메이저(column-major, 열 우선 배열)로 펼친 float 16개로 나온다(04장).

왜 유용한가. 3D 안경·모자·마스크 같은 가상 오브젝트를 얼굴 자세(pose)에 맞춰 그리려면 이 변환이 필요하다. AR 필터나 아바타가 대표 응용이다.

레거시에서는 어땠나. 레거시 Face Mesh의 표준 솔루션 출력에는 이 행렬이 없다. 같은 정보를 얻으려면 별도의 Face Geometry 모듈을 따로 끼워 face pose transform을 계산해야 했다(이슈 #2707, #1642). 곧바로 나오는 출력이 아니었다. 신 API는 이를 옵션 한 줄로 표준화했다(output_facial_transformation_matrixes=True).

아래 그림은 두 API의 출력 묶음을 나란히 둔 것이다.

Face Landmarker outputs

face_landmarks 478

face_blendshapes 52 — NEW

facial_transformation_matrixes 4x4 — NEW

Face Mesh outputs

multi_face_landmarks 468 or 478

랜드마크(점)는 양쪽 다 있다. 표정 계수와 자세 행렬은 Landmarker가 새로 표준 출력에 더한 것이다.

광고 · Advertisements

5.5 API·설정 차이

모델 제공 방식: 내장 그래프 vs .task 번들

구분 Face Mesh (Legacy) Face Landmarker (Tasks)
모델 위치 라이브러리 내장 그래프 face_landmark_front_cpu.binarypb 외부 .task 파일(face_landmarker.task)
주입 방식 없음(클래스 생성만으로 동작) BaseOptions(model_asset_path='…/face_landmarker.task')
의미 모델이 코드에 묶여 있음 모델 파일을 갈아끼울 수 있음(버전·커스텀 교체가 쉬움)

실행 모드: static_image_mode vs running_mode 3종

Face Mesh는 static_image_mode(불리언) 하나로 갈랐다. True면 매 프레임 새로 검출하고, False면 추적(tracking)을 쓴다.

Face Landmarker는 세 모드를 명시한다(02장).

  • IMAGE: 단일 이미지. detect()로 부른다.
  • VIDEO: 타임스탬프가 붙은 디코드 프레임. detect_for_video(image, timestamp_ms)로 부른다.
  • LIVE_STREAM: 실시간 스트림. detect_async(image, timestamp_ms)로 밀어넣고, 결과는 비동기 result_callback으로 받는다.

Face Landmarker running_mode

IMAGE

detect

VIDEO

detect_for_video timestamp

LIVE_STREAM

detect_async timestamp

result_callback

Face Mesh

static_image_mode True or False

process(image)

설정 옵션 대응표

의미 Face Mesh (Legacy) Face Landmarker (Tasks) 기본값 비교
모델 경로 (없음, 내장) base_options.model_asset_path
실행 모드 static_image_mode (bool) running_mode (IMAGE/VIDEO/LIVE_STREAM) Mesh False / Tasks IMAGE
최대 얼굴 수 max_num_faces (기본 1) num_faces (기본 1, 정수>0) 동일(1)
iris 정밀화 refine_landmarks (기본 False → True 시 478) (해당 옵션 없음, 항상 478) 의미 다름
검출 신뢰도 min_detection_confidence (0.5) min_face_detection_confidence (0.5) 동일(0.5)
존재 신뢰도 (없음) min_face_presence_confidence (0.5) Tasks 신규
추적 신뢰도 min_tracking_confidence (0.5) min_tracking_confidence (0.5) 동일(0.5)
blendshape 출력 (없음) output_face_blendshapes (bool, 기본 False) Tasks 신규
transform 행렬 출력 (없음) output_facial_transformation_matrixes (bool, 기본 False) Tasks 신규
콜백 (없음) result_callback (LIVE_STREAM 전용) Tasks 신규
가속 delegate (옵션 노출 없음) base_options.delegate (CPU/GPU) Tasks 신규

근거: 레거시 FaceMesh.__init__ 시그니처는 static_image_mode=False, max_num_faces=1, refine_landmarks=False, min_detection_confidence=0.5, min_tracking_confidence=0.5다. 신 API의 옵션·기본값은 공식 표 기준이다(상세는 06장).

혼동 주의 3 — refine_landmarks vs 항상 478. 레거시에서는 478을 받으려면 refine_landmarks=True를 켜야 했다. 끄면 468이었다. Face Landmarker는 그런 토글이 없다. 출력 랜드마크가 항상 478이다. 그래서 옮길 때 "468로 가정한 인덱싱"이 있으면 점검해야 한다(03장).

혼동 주의 4 — min_face_presence_confidence는 신규. 레거시에는 검출과 추적, 두 임계값만 있었다. 신 API는 그 사이에 "얼굴이 실제로 있는가"를 보는 presence confidence를 따로 둔다. 세 임계값 모두 기본 0.5다.

LIVE_STREAM 콜백 모델과 delegate

LIVE_STREAM 모드는 결과를 반환값으로 받지 않는다. 콜백으로 받는다. 콜백 시그니처는 Python에서 def callback(result: FaceLandmarkerResult, output_image: mp.Image, timestamp_ms: int)다. 옵션에 result_callback=callback을 넘기고, 입력은 detect_async(image, timestamp_ms)로 밀어넣는다. 레거시 Face Mesh에는 이런 비동기 콜백이 없었다. process() 호출이 결과를 그 자리에서 동기로 돌려줬다.

가속기는 신 API의 BaseOptionsdelegate 필드로 고른다. CPU(0) 또는 GPU(1)이고, 기본은 None이다. 다만 GPU delegate가 되는지는 플랫폼 제약이 있다(06장). 레거시는 이런 delegate 선택을 사용자 API로 내놓지 않았다.

코드 형태 한눈 비교 (개념적)

# Legacy Face Mesh
import mediapipe as mp
mp_face_mesh = mp.solutions.face_mesh
with mp_face_mesh.FaceMesh(
        static_image_mode=False,
        max_num_faces=1,
        refine_landmarks=True,          # 켜야 478
        min_detection_confidence=0.5,
        min_tracking_confidence=0.5) as fm:
    res = fm.process(rgb_image)         # 동기 반환
    for face in res.multi_face_landmarks:   # 478 점
        ...
# Face Landmarker (Tasks API)
from mediapipe.tasks import python
from mediapipe.tasks.python import vision

opts = vision.FaceLandmarkerOptions(
    base_options=python.BaseOptions(model_asset_path='face_landmarker.task'),
    running_mode=vision.RunningMode.LIVE_STREAM,
    num_faces=1,
    output_face_blendshapes=True,                  # NEW
    output_facial_transformation_matrixes=True,    # NEW
    result_callback=on_result)                     # NEW (비동기)
with vision.FaceLandmarker.create_from_options(opts) as fl:
    fl.detect_async(mp_image, timestamp_ms)        # 결과는 on_result로
# on_result(result, output_image, ts):
#   result.face_landmarks / result.face_blendshapes / result.facial_transformation_matrixes

두 코드의 모양 차이가 곧 마이그레이션 작업의 윤곽이다. 모델 파일을 넣고, running_mode를 고르고, 필요한 신규 출력을 켠다.

5.6 플랫폼 통일성

Tasks API는 Android, iOS, Python, Web(JS)에서 같은 개념·옵션 이름으로 동작한다. BaseOptions(.task) + …Options(running_mode, num_faces, output_*) + detect/detectForVideo/detectAsync라는 한 패턴이 플랫폼을 가로질러 같다. 그래서 한 플랫폼에서 익힌 사용법이 다른 플랫폼으로 거의 그대로 넘어간다.

레거시 Solutions는 솔루션과 플랫폼마다 제공 형태와 옵션 표현이 흩어져 있었다. 같은 "얼굴 메시"라도 Python·Web·Android 사용법이 서로 달랐다. 이 불일치가 새 API로 옮긴 동기 중 하나다.

Tasks API — one pattern across platforms

Android

iOS

Python

Web JS

BaseOptions(.task) + Options + detect/forVideo/async

5.7 마이그레이션 관점 — 옮길 때 주의점

레거시 Face Mesh 코드를 Face Landmarker로 옮길 때 점검할 항목이다.

  1. 좌표 정규화는 동일. 두 API 모두 x, y를 이미지 폭·높이로 0~1 정규화하고, z는 상대 깊이다. 픽셀이 필요하면 똑같이 x*width, y*height로 환산한다. 좌표 변환 로직은 대체로 그대로 쓴다.
  2. 랜드마크 인덱스 토폴로지 호환. 478 메시 토폴로지(468 mesh + 10 iris)는 같은 canonical 토폴로지를 따른다. 특정 인덱스(눈·입·코끝)를 하드코딩해 쓰던 코드는 대체로 호환된다(03장).
  3. 468 가정 제거. 레거시에서 refine_landmarks=False로 468개를 가정해 배열 크기나 인덱스를 쓰던 코드가 있다면 점검한다. Landmarker는 항상 478이라 iris 인덱스(468~477)가 늘 붙는다.
  4. 출력 필드명 변경. multi_face_landmarksface_landmarks로 바뀐다. 결과 객체 구조와 접근 경로가 달라진다.
  5. 실행 모드·호출 방식 변경. process() 동기 호출이 detect() / detect_for_video(ts) / detect_async(ts)+callback으로 바뀐다. 실시간 파이프라인은 콜백 기반으로 다시 짠다. 타임스탬프가 단조 증가하도록 관리하는 것도 포함이다.
  6. 모델 파일 배포. 더는 내장 그래프가 아니다. face_landmarker.task 파일을 앱에 동봉하거나 내려받아 두고, model_asset_path로 지정한다.
  7. 신규 출력은 명시적으로 켠다. blendshape와 transform 행렬은 기본이 꺼짐(False)이다. 필요하면 output_face_blendshapes=True, output_facial_transformation_matrixes=True를 명시한다. 켜지 않으면 레거시처럼 랜드마크만 나온다.
  8. 성능 특성 변화 가능성. 같은 작업에서 Tasks Face Landmarker가 레거시보다 체감 반응이 다르다는 보고가 있다(환경 의존, 추정 수준, 이슈 #5699). delegate(CPU/GPU)와 running_mode 설정으로 튜닝이 필요할 수 있다.

아래 그림은 이 점검을 순서대로 본 것이다.

Legacy Face Mesh code

Swap output field name

Load .task via BaseOptions

Pick running_mode + callback

Assume 478 always

Enable blendshape / matrix if needed

Tune delegate CPU or GPU

5.8 종합 비교표

Face Mesh (Legacy Solutions) Face Landmarker (Tasks API)
프레임워크 MediaPipe (Legacy) Solutions MediaPipe Tasks API
상태/시점 지원 종료 2023-03-01, as-is 현행 권장
Python 진입점 mp.solutions.face_mesh.FaceMesh mp.tasks.vision.FaceLandmarker
JS 패키지 @mediapipe/face_mesh @mediapipe/tasks-vision
모델 제공 내장 그래프 binarypb 외부 .task 번들 + base_options
번들 내 모델 수 검출+메시 (blendshape 없음) 검출 + 메시 + blendshape (3개)
랜드마크 468 / refine_landmarks로 478 항상 478
Blendshapes(52) ✓ (옵션, 기본 off)
Transform matrix(4×4) ✗(표준 출력 아님) ✓ (옵션, 기본 off)
출력 필드 multi_face_landmarks face_landmarks, face_blendshapes, facial_transformation_matrixes
실행 모드 static_image_mode bool IMAGE / VIDEO / LIVE_STREAM
호출 process() 동기 detect / detect_for_video / detect_async
실시간 콜백 result_callback
신뢰도 옵션 detection, tracking detection, presence, tracking
최대 얼굴 max_num_faces(1) num_faces(1)
delegate(CPU/GPU) 사용자 옵션 미노출 base_options.delegate (GPU 플랫폼 제약)
플랫폼 일관성 분산 Android/iOS/Python/Web 통일
좌표 정규화 0~1 정규화 x·y, 상대 z 동일

표기 규약: "✓/✗"는 해당 API의 표준 출력·옵션 기준이다. 레거시에서 별도 모듈을 끼워 우회로 얻을 수 있는 경우는 "표준 출력 아님"으로 구분했다. 출처로 확정되지 않은 성능 비교는 "추정"으로 명시했다.

다음 장: 06. 성능·요구사항·플랫폼·실행 모드 — 현행 Tasks API를 실제로 돌리려면 무엇이 필요하고 얼마나 빠른가.


Sources (공식 우선)

  • MediaPipe Solutions guide — 레거시 deprecation(2023-03-01), as-is 제공, 신 Vision Tasks 목록, 플랫폼: https://ai.google.dev/edge/mediapipe/solutions/guide
  • Face landmark detection guide (Face Landmarker) — 478 랜드마크 / 52 blendshape / transform 행렬, 옵션·기본값, .task 번들 3개 모델(192×192 / 256×256 / 1×146×2): https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker
  • Face landmark detection — Python guide — BaseOptions(model_asset_path), FaceLandmarkerOptions, result_callback, FaceLandmarkerResult: https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker/python
  • 레거시 Face Mesh 페이지(현재 Face Landmarker로 forward): https://github.com/google-ai-edge/mediapipe/blob/master/docs/solutions/face_mesh.md
  • 레거시 소스 face_mesh.pyFaceMesh.__init__ 기본값, FACEMESH_NUM_LANDMARKS=468/…_WITH_IRISES=478, multi_face_landmarks, face_landmark_front_cpu.binarypb: https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/python/solutions/face_mesh.py
  • base_options.pymodel_asset_path/model_asset_buffer/delegate(CPU=0, GPU=1, default None): https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/tasks/python/core/base_options.py
  • MediaPipe 3D Face Transform(블로그) — canonical face model, 4×4 face pose transform 행렬: https://developers.googleblog.com/mediapipe-3d-face-transform/
  • 이슈 #2707 / #1642 — 레거시에서 face pose transform을 별도 Face Geometry로 얻던 정황: https://github.com/google/mediapipe/issues/2707 , https://github.com/google/mediapipe/issues/1642
  • 이슈 #5699 — Tasks Face Landmarker vs 레거시 체감 성능 보고(추정·환경 의존): https://github.com/google-ai-edge/mediapipe/issues/5699
  • delegate 사용 이슈 #5447 — CPU/GPU delegate 지정과 플랫폼 제약: https://github.com/google-ai-edge/mediapipe/issues/5447