05. 기존 Face Mesh와의 차이 — 레거시에서 무엇이 달라졌나
Contents
- 5.1 서두 요약 — 한눈에
- 5.2 두 API의 정체성 — 같은 일, 다른 세대
- 5.3 .task 번들이 품은 모델들
- 5.4 출력(output) 차이 — 가장 중요한 차이
- 한눈 비교표
- 신규 출력 ① — 52 blendshapes
- 신규 출력 ② — 4×4 facial transformation matrix
- 5.5 API·설정 차이
- 모델 제공 방식: 내장 그래프 vs .task 번들
- 실행 모드: static_image_mode vs running_mode 3종
- 설정 옵션 대응표
- LIVE_STREAM 콜백 모델과 delegate
- 코드 형태 한눈 비교 (개념적)
- 5.6 플랫폼 통일성
- 5.7 마이그레이션 관점 — 옮길 때 주의점
- 5.8 종합 비교표
- Sources (공식 우선)
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에서 같은 개념·옵션 이름을 쓴다. 레거시는 플랫폼별 제공 형태가 흩어져 있었다.
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절).
아래 그림은 두 세대의 내부 경로를 나란히 둔 것이다.
점선 경로(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 = 468과FACEMESH_NUM_LANDMARKS_WITH_IRISES = 478상수가 있고, 출력 필드는multi_face_landmarks다. 신 API의FaceLandmarkerResult는face_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의 출력 묶음을 나란히 둔 것이다.
랜드마크(점)는 양쪽 다 있다. 표정 계수와 자세 행렬은 Landmarker가 새로 표준 출력에 더한 것이다.
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 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_landmarksvs 항상 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의 BaseOptions가 delegate 필드로 고른다. 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로 옮긴 동기 중 하나다.
5.7 마이그레이션 관점 — 옮길 때 주의점
레거시 Face Mesh 코드를 Face Landmarker로 옮길 때 점검할 항목이다.
- 좌표 정규화는 동일. 두 API 모두
x, y를 이미지 폭·높이로 0~1 정규화하고,z는 상대 깊이다. 픽셀이 필요하면 똑같이x*width, y*height로 환산한다. 좌표 변환 로직은 대체로 그대로 쓴다. - 랜드마크 인덱스 토폴로지 호환. 478 메시 토폴로지(468 mesh + 10 iris)는 같은 canonical 토폴로지를 따른다. 특정 인덱스(눈·입·코끝)를 하드코딩해 쓰던 코드는 대체로 호환된다(03장).
- 468 가정 제거. 레거시에서
refine_landmarks=False로 468개를 가정해 배열 크기나 인덱스를 쓰던 코드가 있다면 점검한다. Landmarker는 항상 478이라 iris 인덱스(468~477)가 늘 붙는다. - 출력 필드명 변경.
multi_face_landmarks가face_landmarks로 바뀐다. 결과 객체 구조와 접근 경로가 달라진다. - 실행 모드·호출 방식 변경.
process()동기 호출이detect()/detect_for_video(ts)/detect_async(ts)+callback으로 바뀐다. 실시간 파이프라인은 콜백 기반으로 다시 짠다. 타임스탬프가 단조 증가하도록 관리하는 것도 포함이다. - 모델 파일 배포. 더는 내장 그래프가 아니다.
face_landmarker.task파일을 앱에 동봉하거나 내려받아 두고,model_asset_path로 지정한다. - 신규 출력은 명시적으로 켠다. blendshape와 transform 행렬은 기본이 꺼짐(False)이다. 필요하면
output_face_blendshapes=True,output_facial_transformation_matrixes=True를 명시한다. 켜지 않으면 레거시처럼 랜드마크만 나온다. - 성능 특성 변화 가능성. 같은 작업에서 Tasks Face Landmarker가 레거시보다 체감 반응이 다르다는 보고가 있다(환경 의존, 추정 수준, 이슈 #5699). delegate(CPU/GPU)와 running_mode 설정으로 튜닝이 필요할 수 있다.
아래 그림은 이 점검을 순서대로 본 것이다.
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.py—FaceMesh.__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.py—model_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