728x90
반응형
미디어파이프 메쉬 모델 소개
1. 미디어파이프란?
미디어파이프(MediaPipe)는 구글에서 개발한 멀티모달 머신러닝 파이프라인 프레임워크예요.
영상·음성·센서 데이터를 빠르고 효율적으로 처리할 수 있도록 다양한 사전 학습된 AI 모델을 제공하죠.
특히 컴퓨터 비전 분야에서 강력하게 활용되며, 얼굴 인식·포즈 추정·손동작 추적 등 실시간 애플리케이션에 널리 쓰입니다.
2. 메쉬(Mesh) 모델이란?
메쉬 모델은 영상 속 객체를 단순히 사각형 박스로 인식하는 것이 아니라, 정밀한 점(landmark) 좌표를 기반으로 3D 형태를 예측하는 방식입니다.
예를 들어:
- Face Mesh : 얼굴의 468개 랜드마크를 감지해 3D 형태로 분석
- Hand Mesh : 손가락 관절 21개 포인트를 추적해 제스처 인식 가능
- Body Pose Mesh : 전신 33개 관절 포인트를 기반으로 자세 분석
즉, 메쉬 모델은 단순한 ‘위치 감지’를 넘어서 세밀한 동작 이해와 3D 시뮬레이션을 가능하게 합니다.
![]() |
![]() |
3. 활용 사례
- 🎭 증강현실(AR) : 얼굴 필터, 가상 화장, 캐릭터 마스크 적용
- 🖐 제스처 인식 : 손가락 모양으로 컴퓨터나 로봇 제어
- 🏃 스포츠 분석 : 선수의 동작 자세 분석 및 피드백
- 🧑⚕️ 헬스케어 : 재활 훈련에서 환자의 동작 추적 및 평가
- 🎮 게임 인터페이스 : 손과 몸을 활용한 모션 게임
4. 파이썬으로 코드
import cv2
import mediapipe as mp
# MediaPipe FaceMesh 초기화
mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils
# 흰색 선 스타일 정의
white_line = mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=1)
# 웹캠 열기
cap = cv2.VideoCapture(0)
with mp_face_mesh.FaceMesh(
max_num_faces=1, # 최대 감지 얼굴 수
refine_landmarks=True, # 눈/입술/홍채 정밀 검출
min_detection_confidence=0.5,
min_tracking_confidence=0.5
) as face_mesh:
while cap.isOpened():
success, frame = cap.read()
if not success:
print("웹캠을 불러올 수 없습니다.")
break
# --- 프레임 좌우 반전 (거울 모드) ---
frame = cv2.flip(frame, 1)
# OpenCV는 BGR, MediaPipe는 RGB
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 얼굴 메쉬 추론
results = face_mesh.process(frame_rgb)
# 출력용으로 다시 BGR 변환
frame.flags.writeable = True
frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
# 랜드마크 그리기
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# 전체 메쉬 (흰색)
mp_drawing.draw_landmarks(
image=frame_bgr,
landmark_list=face_landmarks,
connections=mp_face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=white_line
)
# 결과 출력
cv2.imshow('Face Mesh White Lines', frame_bgr)
# ESC로 종료
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
5. 입술 랜드마크 활용하기
- 윗입술과 아랫입술의 랜드마크 좌표를 활용하기
- 두 랜드마크 간의 거리를 계산하기
- 계산된 거리를 통해 입이 열렸는지 닫혔는지 판별하기
- 윗입술(Upper Lip)
- 외곽(upper outer): [61, 185, 40, 39, 37, 0, 267, 269, 270, 409, 291]
- 안쪽(upper inner): [78, 191, 80, 81, 82, 13, 312, 311, 310, 415, 308]
- 아랫입술(Lower Lip)
- 외곽(lower outer): [61, 146, 91, 181, 84, 17, 314, 405, 321, 375, 291]
- 안쪽(lower inner): [78, 95, 88, 178, 87, 14, 317, 402, 318, 324, 308]
📌 참고: 중앙 기준으로 보면
- 윗입술 중앙(inner) → 13번
- 아랫입술 중앙(inner) → 14번
6. 랜드마크 좌표 가져오기
h, w, _ = frame_bgr.shape
landmark = face_landmarks.landmark[13]
x = int(landmark.x * w)
y = int(landmark.y * h)
h, w, _ = frame_bgr.shape frame_bgr는 OpenCV로 읽어온 현재 프레임(이미지) .shape는 이미지 크기를 알려줍니다. h → 이미지 높이(height, 세로 픽셀 수) w → 이미지 너비(width, 가로 픽셀 수) _ → 채널 수(색상, BGR이므로 3) 즉, 이 코드로 현재 프레임의 너비와 높이를 가져옵니다. |
landmark = face_landmarks.landmark[13] face_landmarks.landmark는 얼굴의 468개 랜드마크 리스트입니다. 그 중 13번 인덱스를 선택 → 윗입술 특정 지점에 해당하는 좌표. landmark는 다음 값을 갖습니다: landmark.x : 0~1 사이의 가로 위치 (정규화된 비율) landmark.y : 0~1 사이의 세로 위치 (정규화된 비율) landmark.z : 카메라와의 깊이 상대값 (주로 3D 계산할 때 사용) |
x = int(landmark.x * w) y = int(landmark.y * h) landmark.x와 landmark.y는 정규화된 좌표라서 화면 크기와는 무관한 0~1 값입니다. 따라서 실제 픽셀 단위 좌표로 변환하려면 width와 height를 곱해야 합니다. x = landmark.x * w → 가로 픽셀 위치 y = landmark.y * h → 세로 픽셀 위치 int()로 변환 → 정수 픽셀 좌표로 변환 |
7. puttext() 함수를 활용하여 좌표값 출력하기.
text = f"13: ({x}, {y})"
cv2.putText(frame_bgr,text, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
“63번 랜드마크 좌표 (x, y)”라는 텍스트를 초록색 글씨로 영상 위에 표시
8. 최종 코드
import cv2
import mediapipe as mp
# MediaPipe FaceMesh 초기화
mp_face_mesh = mp.solutions.face_mesh
mp_drawing = mp.solutions.drawing_utils
# 흰색 선 스타일 정의
white_line = mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=1)
# 웹캠 열기
cap = cv2.VideoCapture(0)
with mp_face_mesh.FaceMesh(
max_num_faces=1, # 최대 감지 얼굴 수
refine_landmarks=True, # 눈/입술/홍채 정밀 검출
min_detection_confidence=0.5,
min_tracking_confidence=0.5
) as face_mesh:
while cap.isOpened():
success, frame = cap.read()
if not success:
print("웹캠을 불러올 수 없습니다.")
break
# --- 프레임 좌우 반전 (거울 모드) ---
frame = cv2.flip(frame, 1)
# OpenCV는 BGR, MediaPipe는 RGB
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 얼굴 메쉬 추론
results = face_mesh.process(frame_rgb)
# 출력용으로 다시 BGR 변환
frame.flags.writeable = True
frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
# 랜드마크 그리기
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
# 전체 메쉬 (흰색)
mp_drawing.draw_landmarks(
image=frame_bgr,
landmark_list=face_landmarks,
connections=mp_face_mesh.FACEMESH_TESSELATION,
landmark_drawing_spec=None,
connection_drawing_spec=white_line
)
# ---- 추가 부분: 윗입술 13번 좌표 출력 ----
h, w, _ = frame_bgr.shape
landmark = face_landmarks.landmark[13] # 윗입술 중앙
x, y = int(landmark.x * w), int(landmark.y * h)
# 좌표에 원 표시
cv2.circle(frame_bgr, (x, y), 3, (0, 255, 0), 1)
# 좌표 텍스트 출력
coord_text = f"13: ({x}, {y})"
cv2.putText(frame_bgr, coord_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# 결과 출력
cv2.imshow('Face Mesh White Lines', frame_bgr)
# ESC로 종료
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
728x90
반응형
'인공지능 기초 수업' 카테고리의 다른 글
Mediapipe 메쉬 모델 입크기를 서보모터 각도 값으로 변환하기. (0) | 2025.09.03 |
---|---|
Roboflow #2. 이미지 라벨링, 데이터 셋 만들기. (3) | 2025.09.01 |
Roboflow #1. 활용 이미지 데이터 업로드 하기. (2) | 2025.09.01 |
kaggle 에서 이미지 데이터 받아오기. (2) | 2025.09.01 |
mediapipe 매쉬 모델활용 얼굴 트레킹봇 만들기. (4) | 2025.08.14 |