Pose as Data: MediaPipe와 GPT-4o를 활용한 실시간 AI 물리치료사 구축
Source: Dev.to
집에서 물리 치료(PT)를 하는 것은 양날의 검이다. 한편으로는 잠옷을 입고 할 수 있지만, 다른 한편으로는 자신의 “스쿼트”가 우아한 학처럼 보이는지 아니면 접이식 정원 의자처럼 보이는지 전혀 알 수 없다. 잘못된 자세는 단순히 효과가 없는 것이 아니라 위험하다.
이 튜토리얼에서는 순수 Computer Vision과 Generative AI 사이의 격차를 메우고자 한다. 우리는 MediaPipe를 사용한 real‑time pose estimation을 이용해 골격 데이터를 JSON으로 직렬화하고, 이를 WebSockets를 통해 GPT‑4o‑mini에 전달하여 전문가 수준의 교정 피드백을 제공하는 시스템을 구축한다. AI‑driven fitness, human‑computer interaction, 혹은 real‑time multimodal LLMs에 관심이 있든, 이 가이드는 최신 비전‑투‑텍스트 파이프라인의 전체 스택을 다룬다.
아키텍처: 픽셀에서 처방까지
비디오 스트림을 실행 가능한 의료 조언으로 어떻게 전환할 수 있을까요? 비밀은 “포즈를 데이터로 다루는” 데 있습니다. 원시 비디오 프레임을 LLM에 보내는 대신(비용이 많이 들고 느리기 때문에), 우리는 골격 관절의 3D 좌표를 추출하고 움직임의 수학적 표현을 전송합니다.
graph TD
A[User Webcam] -->|Video Frame| B(MediaPipe Pose)
B -->|3D Landmarks| C{Data Processor}
C -->|JSON Skeleton| D[FastAPI WebSocket]
D -->|Contextual Prompt| E[GPT‑4o‑mini]
E -->|Corrective Text/Speech| F[Frontend UI]
F -->|Real‑time Feedback| A
전제 조건
따라 하려면 다음이 필요합니다:
- MediaPipe – 고정밀 바디 트래킹.
- OpenCV – 비디오 스트림 처리.
- FastAPI / WebSockets – 저지연 통신.
- OpenAI SDK – GPT‑4o‑mini의 추론 기능에 접근.
Step 1: MediaPipe를 사용한 골격 랜드마크 추출
먼저 비디오 스트림에서 33개의 필수 랜드마크(어깨, 무릎, 발목 등)를 추출해야 합니다. MediaPipe는 각 랜드마크에 대해 (x, y, z) 좌표를 제공합니다.
import cv2
import mediapipe as mp
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5)
def get_skeletal_data(frame):
# BGR 이미지를 RGB로 변환
image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = pose.process(image_rgb)
if not results.pose_landmarks:
return None
# 운동과 관련된 주요 포인트 추출(예: 스쿼트)
landmarks = results.pose_landmarks.landmark
data = {
"left_knee": {"x": landmarks[25].x, "y": landmarks[25].y, "z": landmarks[25].z},
"right_knee": {"x": landmarks[26].x, "y": landmarks[26].y, "z": landmarks[26].z},
"hip": {"x": landmarks[24].x, "y": landmarks[24].y}
}
return data
Step 2: The Real‑Time Pipeline (WebSockets)
실시간 피드백을 원하기 때문에 표준 REST 요청을 기다릴 수 없습니다. WebSockets를 사용하여 랜드마크 데이터를 백엔드로 스트리밍합니다.
from fastapi import FastAPI, WebSocket
import json
app = FastAPI()
@app.websocket("/ws/rehab")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
# Receive skeletal data from the frontend/client
client_data = await websocket.receive_text()
skeleton = json.loads(client_data)
# Trigger GPT‑4o analysis every 30 frames or on specific movement triggers
feedback = analyze_pose_with_gpt(skeleton)
await websocket.send_text(feedback)
3단계: “물리 치료사”에게 입력하기 (GPT‑4o‑mini)
프롬프트에서 마법이 일어납니다. 우리는 LLM에 좌표 데이터를 제공하고 물리 치료사 역할을 하도록 지시합니다.
import openai
def analyze_pose_with_gpt(skeleton_data):
prompt = f"""
You are a professional Physical Therapist.
Analyze these 3D coordinates of a patient performing a squat:
{skeleton_data}
If the knee y‑coordinate is higher than the hip y‑coordinate, they aren't deep enough.
If the knees are converging (check x‑coordinates), warn about valgus stress.
Provide a 1‑sentence concise correction.
"""
response = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
max_tokens=50
)
return response.choices[0].message.content
팁: 고급 구현 패턴
위와 같이 MVP를 만들 수 있지만, 프로덕션 수준의 의료 또는 피트니스 앱은 다음을 처리해야 합니다:
- 지터 및 가림 (신체 부위가 가려질 때)
- 시간적 분석 (현재 프레임을 지난 10프레임과 비교)
랜드마크를 부드럽게 하기 위해 칼만 필터를 구현하거나 비전 작업을 위한 LLM 토큰 사용을 최적화하는 것을 고려하세요. 더 깊이 파고들고 싶다면 **WellAlly Blog**의 기술 기사들을 확인하세요—“멋진 데모”와 “견고한 AI 제품” 사이의 격차를 메우는 개발자들에게 훌륭한 자료입니다.
결론
pose를 데이터로 취급함으로써 “시각”과 “지능”을 분리합니다. MediaPipe가 공간 기하학의 무거운 작업을 처리하고, GPT‑4o‑mini는 섬세한 인간 지시를 제공합니다.
다음 단계는?
- TTS(텍스트‑투‑스피치) 추가 – OpenAI의 Whisper 또는 ElevenLabs를 사용해 “AI 코치”가 실시간으로 사용자와 대화할 수 있게 합니다.
- 시간 논리 – 좌표 시퀀스를 전송하여 AI가 정적인 프레임이 아니라 운동의 템포를 분석할 수 있게 합니다.
AI 기반 피트니스 분야에서 무언가를 만들고 있나요? 진행 상황을 공유해주세요! 🚀
헬스 분야인가요? 아래에 댓글을 남기거나 레포를 공유하세요!
함께 움직임의 미래를 만들어갑시다.
