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

03. 478개 랜드마크 — 종류와 "왜 478개인가"

목차

02장 마지막 단계에서 메시 모델이 478점을 회귀했다. 그 478점이 정확히 무엇이고, 478이라는 숫자가 어디서 왔는지를 이 장에서 본다. 00장에서 정한 용어(랜드마크, 메시, 정규화 좌표, canonical face model, 회귀)를 그대로 쓴다.

3.1 핵심부터 — 478 = 468 + 10

이 책에서 가장 자주 나온 질문이 "왜 점이 478개나 되는가"다. 답의 절반은 의외로 단순하다. 478은 한 숫자가 아니라 서로 다른 두 출처를 더한 값이다.

  • 468개 = 얼굴 표면 메시(face surface mesh) 랜드마크. 00장에서 본 canonical_face_model(표준 3D 얼굴 모델)의 정점(vertex, 메시를 이루는 꼭짓점) 수와 1:1로 대응한다. 인덱스는 0 ~ 467.
  • 10개 = 홍채(iris) 랜드마크. 눈 하나당 5개(중심 1 + 둘레 4)이고, 양안이니 10개다. 인덱스는 468 ~ 477. 출처는 01장에서 본 별도 모델 MediaPipe Iris(2020-08-06 공개)다.
  • 합이 478이다.

공식 문서도 이 숫자를 그대로 적는다. "The model outputs an estimate of 478 3-dimensional face landmarks."

Face Landmarker output: 478

468 surface mesh

10 iris

index 0 ~ 467

source: canonical_face_model vertices

index 468 ~ 477

source: MediaPipe Iris model

per eye = 5

1 center

4 contour

x 2 eyes = 10

478이 두 출처(표면 메시 468 + 홍채 10)의 합이고, 인덱스가 0부터 477까지 이어 붙는 모습이다.

478을 두 부서를 합친 회사로 생각하면 쉽다. 본사 Face Mesh에 468명이 있었고, 인수한 작은 전문 회사 Iris에 10명이 있었다. 합치면 478명이다. 사번도 본사 0~467번 뒤에 Iris 468~477번을 이어 붙였다.

각 랜드마크는 00장에서 정의한 정규화 좌표 (x, y, z)를 가진다. x, y ∈ [0, 1]로, 이미지 폭과 높이로 나눈 값이다. z는 상대 깊이로, 머리 중심이 원점이고 값이 작을수록 카메라에 가깝다. 절대 거리는 아니다(§3.6).

두 출처를 하나씩 들여다보자. 먼저 468개다.

광고 · Advertisements

3.2 왜 468개인가 — 얼굴 표면 메시

468은 임의로 고른 숫자가 아니다. canonical_face_model의 정점 수다. 공식 저장소의 canonical_face_model.obj 파일이 정점 468개로 이루어져 있고, Face Landmark 모델이 출력하는 468개 랜드마크가 이 정점과 인덱스 단위로 1:1 대응한다.

그래서 모델이 하는 일은 이렇게 풀 수 있다. "이 사람 얼굴에서 표준 메시의 i번 정점은 화면 어디에 있나"를 회귀로 추정한다. 출력은 의미가 고정된 468개 점이다. 어느 프레임, 어느 사람이든 같은 번호의 점은 같은 부위를 가리킨다. 예를 들어 1번은 코끝 근처, 152번은 턱끝 근처다.

왜 이렇게 점을 촘촘히 찍는가. 얼굴은 매끈한 평면이 아니다. 눈두덩, 콧대, 입술의 볼륨, 뺨의 곡률 같은 곡면이다. 점 몇 개로는 이 곡면도, 표정 변화도 담을 수 없다. 468개를 삼각형 그물(mesh)로 이으면 얼굴 표면 전체를 빈틈없이 덮는 면이 만들어진다. 이 면 위에 텍스처(이미지나 메이크업)를 입히거나(UV 매핑), AR 마스크를 씌우거나, blendshape로 표정을 구동할 수 있다.

여기서 이 장의 핵심이 나온다. 고정 토폴로지(fixed topology)의 이점이다. 정점의 3D 위치(XYZ)는 매 프레임 사람마다 바뀐다. 하지만 UV 좌표(텍스처 매핑용 2D 좌표)와 삼각형 연결(triangulation)은 canonical_face_model에서 그대로 물려받는다. 그래서 "i번 점은 텍스처의 어디에 붙고, j·k·l번 점은 한 삼각형을 이룬다" 같은 구조가 늘 똑같다. 덕분에 프레임이 바뀌어도 같은 부위를 추적하고, 리깅과 AR 텍스처 매핑이 안정적으로 작동한다.

runtime landmarks XYZ per frame

face mesh

canonical_face_model

UV texture coords (fixed)

triangulation / topology (fixed)

texture map / AR mask / rigging / blendshape input

정점 위치는 프레임마다 바뀌지만 UV·삼각형 연결은 canonical 모델에서 고정으로 상속돼, 그 위에 텍스처·AR·리깅·blendshape 입력이 얹힌다.

한 가지만 더 짚어 두자. 메시의 길이 단위는 canonical_face_model 기준으로 센티미터(cm)다. 이 정적 공간과 런타임 공간은 얼굴 포즈 변환 행렬로 연결된다(04장 §4). 단, Face Landmarker가 기본으로 돌려주는 (x,y,z)는 이 cm 공간이 아니라 정규화 좌표다(§3.6).

468개로 표면을 덮었다. 그런데 표면만으로는 눈동자가 어디를 보는지, 카메라에서 얼마나 떨어졌는지를 알 수 없다. 그래서 10개를 더했다.

3.3 왜 +10개인가 — 홍채(iris) 랜드마크

이 10개는 표면 메시 468개와 출처가 다르다. 01장에서 본 별도 모델 MediaPipe Iris가 더한 점이다. Iris의 동작은 단순하다. 먼저 Face Mesh로 얼굴을 잡고, 거기서 눈 영역만 잘라내(crop) 정밀하게 추정한다. 블로그도 그렇게 적는다. "From this mesh, we isolate the eye region."

점의 구성은 눈 하나당 5개다. 중심(center) 1점에 둘레(contour ring) 4점을 더한다. 양안이니 5 × 2 = 10이다.

왜 굳이 더했나. 이유는 둘이다.

  • 시선 추정(eye tracking)과 동공 추적. 홍채의 중심과 둘레를 알면 눈동자가 어디를 보는지, 깜빡이는지, 동공이 어디에 있는지를 알 수 있다. 04장에서 보는 eyeLookIn/Out/Up/Down 블렌드셰이프가 바로 이 10점 덕에 나온다.
  • 거리(깊이) 추정. 인간의 수평 홍채 지름은 인구 전반에서 약 11.7 ± 0.5 mm로 거의 일정하다. 이 생체 상수를 쓰면 화면 속 홍채의 크기만 보고 카메라와 피사체 사이 거리를 추정할 수 있다. 보고된 정확도는 평균 상대오차 4.3%(표준편차 2.4%)이고, 안경을 쓰면 4.8%(표준편차 3.1%)다.

x2 left and right

one eye (5 points)

1 center

contour 1

contour 2

contour 3

contour 4

10 iris landmarks total

MediaPipe Iris model (2020-08)

눈 하나가 중심 1점 + 둘레 4점 = 5점이고, 양안을 합쳐 홍채 10점이 된다.

혼동 주의 — 468 vs 478. 구형 레거시 Face Mesh는 기본이 468개였다. refine_landmarks=True 옵션을 켜야 478개가 나왔다(눈·입술 좌표를 정제하고 홍채를 추가). 이 정제는 01장의 Attention Mesh 모델을 적용해 눈·입술·홍채를 의미 영역 단위로 다듬는 동작이다. 반면 현행 Tasks API의 Face Landmarker는 기본으로 478개를 출력한다. 두 API의 차이는 05장에서 자세히 다룬다.

이제 478점이 얼굴 어디에 어떻게 흩어져 있는지를 부위별로 본다.

광고 · Advertisements

3.4 feature의 종류 — 얼굴 영역별 그룹

478개를 "얼굴의 어느 부위인가"로 묶어 보자. MediaPipe는 부위별 윤곽선을 그리는 FACEMESH_* 연결 상수(connection constants)를 제공한다. 이 상수에 등장하는 인덱스로 영역을 식별할 수 있다.

표를 읽기 전에 "점 수"의 의미부터 못 박자. 아래 표의 "서로 다른 점 수"는 각 영역의 윤곽 연결선(connection)에 등장하는 서로 다른 인덱스 수다. 즉 윤곽선을 그리는 데 쓰는 점만 센 값이다. 얼굴 안쪽을 메우는 테셀레이션(tessellation, 면을 채우는 삼각형) 채움점은 빠진다. 그래서 표의 합은 468이 아니다. 468 전체는 이 윤곽 점에 다수의 테셀레이션 채움점을 더한 것이다.

영역 그룹 표 (FACEMESH_* 상수 기준, 윤곽 연결선 기준)

영역 그룹 (상수) 부위 인덱스 집합(요약) 서로 다른 점 수
FACEMESH_FACE_OVAL 얼굴 윤곽/실루엣 10, 21, 54, 58, 67, 93, 103, 109, 127, 132, 136, 148–150, 152, 162, 172, 176, 234, 251, 288, 297, 323, 332, 338, 356, 361, 365, 377–379, 389, 397, 400, 454 36
FACEMESH_LIPS 입술(외곽+내곽) 0–17, 37, 39–40, 61, 78, 80–82, 84–87, 91, 95, 146, 178, 181, 185, 191, 270, 291, 308–312, 314–318, 321, 324–325, 375, 402, 405, 409, 415 40
FACEMESH_LEFT_EYE 좌안 눈꺼풀 윤곽 249, 263, 362, 373–374, 380–382, 384–390, 398, 466 16
FACEMESH_RIGHT_EYE 우안 눈꺼풀 윤곽 7, 33, 133, 144–145, 153–155, 157–161, 163, 173, 246 16
FACEMESH_LEFT_EYEBROW 좌안 눈썹 276, 282–283, 285, 293–296, 300, 334–336 12
FACEMESH_RIGHT_EYEBROW 우안 눈썹 46, 52–53, 55, 63, 65–66, 70, 105, 107 12
FACEMESH_NOSE 1–6, 19, 45, 48, 64, 94, 97–98, 115, 168, 195, 197, 220, 275, 278, 294, 326–327, 344, 440 25
FACEMESH_RIGHT_IRIS 우안 홍채 (468 center) + 469, 470, 471, 472 5
FACEMESH_LEFT_IRIS 좌안 홍채 (473 center) + 474, 475, 476, 477 5

표 읽기 주의 — 네 가지.

  1. 개수는 "윤곽 상수에 등장하는 점" 기준이다. 윤곽 점만 센 값이라 합이 468이 아니다.
  2. left/right는 "피사체(거울 반대)" 기준이다. 화면에서 보는 좌우와 반대일 수 있다.
  3. 눈(EYE) 상수에는 홍채(IRIS)가 들어 있지 않다. 눈꺼풀 윤곽과 홍채는 별도 상수다.
  4. 홍채 윤곽 상수(FACEMESH_*_IRIS)는 둘레 4점만 연결로 정의한다. 중심점(468/473)은 연결 튜플에는 안 나오지만, 랜드마크 자체는 존재한다.

영역-인덱스 구조 다이어그램

478 landmarks

0 ~ 467 surface mesh (468)

468 ~ 477 iris (10)

FACE_OVAL

LIPS

LEFT_EYE / LEFT_EYEBROW

RIGHT_EYE / RIGHT_EYEBROW

NOSE

tessellation fill (cheeks, forehead, inner face)

RIGHT_IRIS: 468 center, 469-472 ring

LEFT_IRIS: 473 center, 474-477 ring

478점이 표면 메시(영역별 윤곽 + 테셀레이션 채움)와 홍채로 갈리는 구조다.

478점이 얼굴 위 어디에 분포하는가 (공간 직관)

표와 인덱스만으로는 점이 얼굴 어디에 찍히는지가 잘 그려지지 않는다. 다음 다이어그램은 얼굴을 위에서 아래로 훑으며 각 영역이 대략 어디에 있는지를 보여준다. 정확한 좌표가 아니라 상대 위치 직관을 위한 모식도다.

surrounds

face, top to bottom (subject's left = viewer's right)

forehead: tessellation fill

eyebrows: RIGHT_EYEBROW (subject right) | LEFT_EYEBROW (subject left)

eyes: RIGHT_EYE + RIGHT_IRIS | LEFT_EYE + LEFT_IRIS

nose bridge to tip: NOSE (center column)

cheeks: tessellation fill (left and right)

mouth: LIPS (outer ring + inner ring)

chin and jawline: FACE_OVAL lower arc

FACE_OVAL: full silhouette wrapping all of the above

얼굴을 위에서 아래로 훑으면 이마(채움점), 눈썹, 눈+홍채, 코, 뺨(채움점), 입, 턱·턱선 순으로 영역이 쌓이고, FACE_OVAL이 그 바깥을 감싼다.

이 그림에서 한 가지 패턴이 보인다. 눈과 입술처럼 표정에 중요한 부위는 윤곽 점이 촘촘하다(눈 16점, 입술 40점). 이마와 뺨처럼 넓고 평탄한 부위는 윤곽 점이 적은 대신 테셀레이션 채움점이 면을 채운다.

478점이 진짜 얼굴 사진 위에 번호와 함께 어떻게 찍히는지 직접 보고 싶을 수 있다. 이 책은 사진을 싣지 않지만, 아래 공개 시각 자료가 도움이 된다(영역 구조 자체는 위 두 다이어그램으로 충분히 보였다).

  • MediaPipe 공식 canonical_face_model.obj와 그 UV 좌표 시각화: face_geometry 모듈(아래 Sources).
  • 커뮤니티 정리: lschmelzeisen의 "Understanding MediaPipe FaceMesh Output"(UV·인덱스 오버레이)과 Sander de Snaijer의 "All 478 Landmark Points"(얼굴 위 번호 오버레이). Sources 참조.

영역을 봤으니, 가장 헷갈리는 홍채 인덱스 번호를 정확히 못 박자.

3.5 홍채 인덱스 — 정확한 번호 매핑 (혼동 빈발 지점)

홍채 10점의 인덱스는 MediaPipe 연결 상수에 근거해 다음과 같이 확정된다.

  • FACEMESH_RIGHT_IRIS = [(469,470),(470,471),(471,472),(472,469)] → 둘레 = 469, 470, 471, 472, 중심 = 468
  • FACEMESH_LEFT_IRIS = [(474,475),(475,476),(476,477),(477,474)] → 둘레 = 474, 475, 476, 477, 중심 = 473
인덱스 역할
468 우안(right) 홍채 중심
469, 470, 471, 472 우안 홍채 둘레 4점
473 좌안(left) 홍채 중심
474, 475, 476, 477 좌안 홍채 둘레 4점

출처 간 불일치 주의. 일부 2차 블로그는 "468 = 왼쪽 중심, 473 = 오른쪽 중심"으로 적기도 한다. 하지만 MediaPipe 공식 연결 상수를 보면 둘레 469–472가 RIGHT_IRIS에, 474–477이 LEFT_IRIS에 묶여 있다. 그 사이의 중심점이니 468은 RIGHT, 473은 LEFT로 보는 것이 상수 정의와 일관된다. 이 책은 연결 상수에 근거한 매핑, 즉 468=right, 473=left를 따른다. left/right는 피사체 기준이라 "화면상 왼쪽"과 헷갈리지 말 것.

인덱스를 정했으니, 한 랜드마크가 담는 값의 구조와 좌표 해석 주의점을 본다.

3.6 한 랜드마크의 데이터 구조와 좌표 해석

한 랜드마크가 담는 값

Tasks API에서 한 랜드마크는 NormalizedLandmark 형태이고, 정규화 좌표 (x, y, z)를 가진다.

필드 범위/의미 비고
x [0.0, 1.0], 이미지 으로 정규화 픽셀 = x × image_width
y [0.0, 1.0], 이미지 높이로 정규화 픽셀 = y × image_height
z 상대 깊이. 머리 중심이 원점, 작을수록 카메라에 가까움, 스케일은 x와 대략 동일 절대 거리 아님
visibility / presence face 랜드마크에는 보통 미제공(의미 없음) face는 가려진 점도 추정값을 채워 전 점이 항상 출력

왜 face에는 visibility가 없나. Face Mesh와 Landmarker는 얼굴 한 장에 대해 늘 478점 전체를 회귀한다. 가려진 점도 추정값으로 채운다. 가시성 마스킹이 핵심인 pose나 hand와는 동작 모델이 다르다. 그래서 face 컨테이너는 이 필드를 의미 있게 채우지 않는다(공식 문서가 face에 visibility 정의를 적지 않는 점을 근거로 한 해석).

z의 의미와 한계 (가장 흔한 오해)

z는 상대 깊이다. 원점은 머리 중심이고, 값이 작을수록(더 음수일수록) 카메라에 가깝다. 스케일은 x와 대략 같다(폭을 1로 본 상대 단위). 절대 거리는 아니다. "코끝이 카메라에서 30 cm" 같은 절대값을 z에서 바로 읽으면 안 된다.

실제 거리(metric)가 필요하면 다른 경로를 써야 한다.

  • 홍채 지름 11.7 mm 상수를 쓰는 MediaPipe Iris의 깊이 추정(§3.3), 또는
  • Face Geometry / face pose transformation matrix(센티미터 metric 공간). 이는 기본 (x,y,z) 출력과는 다른 산출물이다(04장 §4).

x

landmark z value

relative depth (head-centered)

NOT absolute distance

use MediaPipe Iris (11.7mm) for metric depth

use face geometry / pose matrix (cm) for metric 3D

z는 머리 중심 기준 상대 깊이일 뿐 절대 거리가 아니며, 실제 거리가 필요하면 Iris의 11.7 mm 상수나 face geometry 행렬을 써야 한다.

좌표계 원점도 한 번 짚고 가자. 이미지 좌표계의 원점은 좌상단(top-left)이다. x는 오른쪽으로, y는 아래쪽으로 증가한다(수학의 y축과 반대 방향). 시각화나 각도 계산을 할 때 부호에 주의한다(00장 §0.5와 같은 규약).

마지막으로 처음 질문 "왜 478개나 되는가"에 정면으로 답하며 이 장을 닫는다.

3.7 "왜 478개나 되는가" — 조밀함의 정당성

점이 적을 때(예: 5~68점)와 478 조밀 메시를 나란히 놓으면 478의 정당성이 한눈에 보인다.

적은 점(예: 5~68점)의 한계 478 조밀 메시가 주는 것
곡면(콧대·뺨·입술 볼륨)을 못 담음 표면 지오메트리를 면 단위로 복원
미세 표정 변화 표현 불가 정점 변위로 표정·입모양·눈 모양을 정밀 표현
프레임마다 점 의미가 흔들릴 수 있음 고정 토폴로지 → 같은 인덱스 = 같은 부위(프레임 간 일관성)
텍스처·리깅 어려움 UV·삼각형 고정 → 텍스처 매핑·리깅·AR 마스크
blendshape 회귀 입력 빈약 478점이 blendshape 모델의 입력(146점 서브셋)으로 쓰임(04장)

점을 정하는 데는 트레이드오프가 있다. 점이 많을수록 표현력과 정밀도는 올라가지만 연산량도 같이 올라간다. 점이 너무 적으면 곡면과 표정을 못 담고, 너무 많으면 모바일 실시간 추론이 깨진다. 모바일에서 수십 FPS로 돌면서 정확도와 속도를 맞춘 균형점이 478이다.

홍채 10점을 굳이 더한 이유도 같은 맥락이다. 표면 메시만으로는 어려운 시선·동공·거리 정보를, 눈이라는 의미 영역에 집중한 별도 추정으로 보강하기 위해서다.

478 dense landmarks

facial surface geometry

frame-to-frame consistency

texture / AR mask / rigging

blendshape regression input -> 52 coeffs

iris 10 -> gaze / pupil / distance

more points = richer but heavier

478 = mobile real-time balance

조밀한 478점이 표면 복원·프레임 일관성·텍스처/AR·blendshape 입력·시선 정보를 동시에 떠받치고, 그 모든 것이 모바일 실시간이라는 제약 안에서 478로 균형을 이룬다.

핵심 한 줄. 478 = 표면 메시 468(canonical_face_model 정점 수, 인덱스 0–467) + 홍채 10(MediaPipe Iris, 눈당 5점 = 중심1+둘레4, 인덱스 468–477). 각 점은 정규화 (x,y,z)이고 z는 상대 깊이다(절대 거리 아님). 조밀하고 고정된 토폴로지여야 곡면·표정 복원, 프레임 일관성, 텍스처·리깅·AR·blendshape 입력이 가능하다. 478이라는 규모는 그래서 정당화된다.

478점 중 146점이 다음 장 블렌드셰이프 모델의 입력이 된다. 특히 방금 본 홍채 10점이 그 입력에 들어가 "시선 방향" 표정 계수를 가능케 한다. 그 메커니즘을 다음 장에서 본다.

다음 장: 04. 블렌드셰이프와 얼굴 변환 행렬


Sources

  • Face Landmarker (공식 문서, "478 3-dimensional face landmarks"; 모델 번들·입력 크기) — Google AI Edge: https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker
  • MediaPipe Iris: Real-time Iris Tracking & Depth Estimation (눈당 5 iris점, 11.7±0.5mm, 상대오차 4.3%/안경 4.8%, 2020-08-06) — Google Research Blog: https://research.google/blog/mediapipe-iris-real-time-iris-tracking-depth-estimation/
  • canonical_face_model.obj (468 정점, UV·삼각형 토폴로지, cm metric) — google-ai-edge/mediapipe: https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/modules/face_geometry/data/canonical_face_model.obj
  • FACEMESH_ 연결 상수* (LIPS/EYE/EYEBROW/OVAL/NOSE/IRIS 인덱스, RIGHT_IRIS 469-472, LEFT_IRIS 474-477) — face_mesh_connections.py: https://github.com/google-ai-edge/mediapipe/blob/master/mediapipe/python/solutions/face_mesh_connections.py
  • MediaPipe Face Mesh 문서 (z = head-centered 상대 깊이, x와 동일 스케일, 작을수록 카메라에 가까움; refine_landmarks 동작) — MediaPipe Face Mesh Wiki: https://github.com/google-ai-edge/mediapipe/wiki/MediaPipe-Face-Mesh
  • Attention Mesh (arXiv:2006.10962) — 478 메시 + 영역 정제(입술/눈/홍채 head), 단일 네트워크 ~30% 빠름: https://arxiv.org/abs/2006.10962
  • NormalizedLandmark (x,y in [0,1], z 상대 깊이) — Google AI Edge API: https://ai.google.dev/edge/api/mediapipe/java/com/google/mediapipe/tasks/components/containers/NormalizedLandmark
  • MediaPipe 3D Face Transform (canonical model · pose transformation matrix · metric=cm) — Google Developers Blog: https://developers.googleblog.com/mediapipe-3d-face-transform/

478점 시각화(외부 공개 자료, 영역·인덱스 직관 보강용):

  • lschmelzeisen, "Understanding MediaPipe FaceMesh Output" (canonical UV·인덱스 오버레이): https://github.com/lschmelzeisen/understanding-mediapipe-facemesh-output
  • Sander de Snaijer, "MediaPipe Face Mesh: All 478 Landmark Points" (얼굴 위 번호 오버레이; 2차 자료, 1차 상수로 교차검증): https://www.sanderdesnaijer.com/blog/mediapipe-face-mesh-landmarks

영역별 "서로 다른 점 수"는 face_mesh_connections.py의 연결 튜플에 등장하는 윤곽 연결선 기준 인덱스를 센 값이고, 얼굴 안쪽 테셀레이션 채움점은 제외한다(§3.4). 인덱스 매핑은 공식 연결 상수를 우선했고, 2차 시각 자료와 충돌하는 부분(홍채 중심 468/473)은 상수 정의를 따랐다.