3D 스켈레톤과 바벨 궤적을 기반으로 역도(인상·용상) 시기의 성공/실패를 자동 판정하는 시스템입니다. 사용자가 Clip을 업로드하면 NLF로 3D Skeleton을 추출하고, YOLO+CoTracker로 바벨/원판 중심 좌표의 궤적을 추출합니다. 이후, 이 둘을 19-node로 정합하여 ST-GCN++ 모델로 분석한 뒤, VLM이 모델 판정결과와 사용자의 input 정보들을 결합하여 VLM모델을 통해 사용자의 자세 피드백 및 훈련 드릴 코칭을 제시합니다· 또한, 실패 판정 시 IWF 공식 규정에 근거하여 추가로 실패 원인 브리핑을 제공합니다.
Sangmyung Univ. Data Science Capstone Project · Team Jerk5
Team Jerk5 — Sangmyung University, Data Science Capstone
한승범 · 팀장 · @nalimeitb
- skeleton extraction 모델 검토 및 NLF 기반 3D 스켈레톤 추출 파이프라인 구축
- 스켈레톤 17 + 바벨 2 노드 19-node 그래프 정합 및 좌표 보정(px→m scale) 구현
- HiCLR in-domain SSL pretrain 및 STGCN++ 5-fold finetuning
- backbone/feature engineering ablation으로 best config 도출
- SMPL-X mesh를 3D Gaussian Splatting으로 렌더링한 3D mesh viewer(정면·측면) 구현
김우식 · 팀원 · @cmkkws
- 경기 영상 metadata 정리 및 PostgreSQL DB 구축
- GCS 기반 원본 영상·결과 storage 구조 설계
- 실패 clip 조회 및 Gemini API 연동
- IWF rule 기반 prompt 설계 및 실패 원인 JSON output 구현
정성령 · 팀원 · @Ryeong-j
- YOLO 기반 barbell detection 자체 구현·검토
- skeleton·barbell 좌표계 정합
- 팀별 모델 통합 single-inference pipeline orchestration 구축
- Streamlit web service(backend·frontend) 및 Cloudflare Pages + KV proxy 고정 URL 배포
정유민 · 팀원 · @jeong-ymj
- 영상 data 수집 방법 조사 및 수집
- YOLO 기반 barbell detection prototype 구현·검토
- 실패 원인 labeling용 rule-based 접근 검토·실험
- user input 기반 LLM API 실패 원인 분석 및 JSON→자연어 변환 구현·검토
한해별 · 팀원 · @byeol-hub
- YOLO 학습용 plate(원판) dataset 수집·구축 및 preprocessing
- YOLO 계열 version·size별 plate detection 학습·성능 비교·분석
- Grounding DINO(zero-shot) + YOLO + CoTracker3 Offline 기반 원판 center 추론 pipeline 구현
올림픽 역도 판정은 lockout(완전 신전)·press-out 같은 미세한 자세를 순간적으로 판단해야 해서, 전문 심판들 간에도 판정이 갈리는 경우가 있습니다. 본 프로젝트는 공개 경기 영상에서 선수의 3D Skeleton와 Barbell trajectory을 검출하고, 이를 학습한 시계열 Graph Convolutional Network 모델로 성공/실패를 일관되게 판정하는 것을 목표로 합니다.
영상 업로드 → 3D 자세·바벨 궤적 검출/Overlay → 성공/실패 판정 → VLM기반 브리핑까지의 실제 화면입니다.
![]() ① 메인 화면 시스템 개요 |
![]() ② 업로드 · 사용자 입력 Clip + 종목·무게·체급 등 |
![]() ③ 판정 결과 성공/실패 · 모델 확신도 · 바벨 궤적 |
![]() ④ 동작 단계 분해 phase별 ideal movements 시퀀스 제시 |
![]() ⑤ AI 브리핑 VLM feedback · 실패원인/규정 리포트 |
![]() ⑥ 3D mesh SMPL-X 정면 · 측면 |
⚠️ 데모 화면의 입력 영상 프레임은 **IWF 공식 방송(YouTube)**에서 발췌한 것으로 저작권은 IWF에 있으며, 비영리 연구·교육 목적의 시스템 시연(공정이용)입니다. 학습 데이터는 이와 별개로 대한역도연맹(KWF) 영상에서 추출했습니다(docs/DATA_CARD.md).
영상 업로드 (구간 trim)
→ NLF single-forward H36M-17 3D
→ YOLO + CoTracker3 바벨 4-stage 트래킹
→ barbell alignment skeleton 17 + barbell 2 = 19-node → (1, 3, T, 19, 1)
→ STGCN++ 19-node, C=5 elbow-amplify(ramp), 5-fold soft-voting
→ 판정 + 오버레이 + 바벨 궤적 + 3D mesh
→ VLM 브리핑 자세 피드백 훈련 드릴 코칭 · 실패 시 IWF 규정 기준 실패 원인 분석
판정 모델은 **HiCLR in-domain SSL로 사전학습한 STGCN++**를 19-node(스켈레톤 17 + 바벨 2)·C=5(xyz 좌표 + 팔꿈치 각도·각속도) 입력에 맞춰 finetuning(backbone/head diff lr full-finetuning)한 것입니다.
- NLF 단일 추론 스켈레톤 — human detect부터 2D·3D 자세까지 한 모델이 한 번에 뽑아냅니다. 따로 lifting 단계를 거치지 않다 보니 그 과정에서 생기던 깊이(z) 압축 경향이 없고, lockout·press-out을 가르는 손목/팔꿈치의 앞뒤 움직임이 잘 살아남습니다(기존 v7 방식보다 실패 동작의 z 범위가 약 2~3배 큽니다).
- 19-node 그래프 (스켈레톤 17 + 바벨 2) — lockout·press-out을 가장 직접적으로 보여주는 게 바벨이라, 바벨 양 끝을 그래프 노드로 함께 넣었습니다. 덕분에 GCN이 "손목과 바벨 사이의 관계"까지 같이 학습합니다.
- HiCLR in-domain SSL — 1,844개라는 넉넉하지 않은 클립 수를 self-supervised learning으로 메워, 성능을 한계치 가까이까지 끌어올렸습니다.
- 팔꿈치 각도 증폭 (C=5) — 팔꿈치 각도와 각속도를 입력 채널로 더하되, lockout이 갈리는 140–170° 구간을 포착할 수 있도록 선형으로 증폭합니다(
elbow_amplify_ramp). 애매한 경계의 hardcase들을 모델이 더 또렷하게 구분하도록 한 장치입니다. - 3D 메시 홀로그램 (SMPL-X × gsplat) — NLF를 돌리면 같이 출력하면 SMPL-X 메시 vertex를 gsplat(3D Gaussian Splatting)으로 정면·측면에서 렌더링합니다. 따로 학습하지 않고 그려내도록 하였으며, 판정 결과를 입체 홀로그램처럼 보여줍니다.
- 5-fold soft-voting — 5개 fold의 확신도를 soft-voting 방식으로 ensemble하여 추론합니다.
NLF Skeleton, 5-fold stratified CV, test set 기준. Snatch/Clean&Jerk 5-fold mean ± std / best fold 표기.
| 종목 | 기준 | accuracy | macro-F1 | AUC | recall (fail) | recall (success) |
|---|---|---|---|---|---|---|
| 인상 (snatch) | 5-fold mean | 0.964 ± 0.017 | 0.961 ± 0.019 | 0.971 ± 0.024 | 0.914 ± 0.048 | 0.996 ± 0.005 |
| best fold | 0.984 | 0.983 | 0.988 | 0.973 | 0.991 | |
| 용상 (clean & jerk) | 5-fold mean | 0.925 ± 0.036 | 0.918 ± 0.039 | 0.949 ± 0.021 | 0.853 ± 0.048 | 0.968 ± 0.036 |
| best fold | 0.956 | 0.952 | 0.971 | 0.899 | 0.991 |
판정에는 NLF 스켈레톤으로 학습한 19-node·C=5(elbow_amplify_ramp, 140–170° clamp-linear) 체크포인트 5개를 soft-voting으로 ensemble. 실험 과정과 근거는 docs/EXPERIMENTS_REPORT.md에서 확인해보실 수 있습니다.
jerk5/
├── skeleton/ 영상 → NLF single-forward로 H36M-17 3D 스켈레톤 추출 (resumable, JSON 로그)
├── barbell/ 영상 → YOLO + CoTracker3 4-stage 파이프라인으로 바벨 2-node 궤적 추적
├── merge_19node/ 스켈레톤 17 + 바벨 2를 19-node로 정합 (바벨 px → root-relative m)
├── action_recognition/ STGCN++ — HiCLR in-domain SSL 사전학습 + 5-fold fine-tune·평가
├── service/ SMPL-X mesh → gsplat 정면·측면 dual-view 홀로그램 렌더 (mesh_gs_poc)
├── app/ Streamlit 통합 데모 — 업로드·trim·판정·결과·VLM 브리핑까지 조율
└── docs/ 실험 리포트 · 데이터 카드 · 참고문헌 · 데모 이미지
전체 구조 펼쳐 보기 (폴더별 주요 파일)
jerk5/
├── skeleton/ 영상 → NLF 17-node 3D skeleton
│ ├── extract_full_nlf.py NLF single-forward 추출 (resumable, JSON 로그)
│ └── config.py NLF / checkpoint 설정
│
├── barbell/ 영상 → YOLO + CoTracker3 바벨 2-node
│ ├── run_pipeline.py 4-stage 진입점 (검출→후처리→시드→추적)
│ ├── inference_motion_v2.py YOLO + motion-darkening plate 검출
│ ├── post_process_seg_v1.py anchor 등급화 · plate/bar 길이 prior
│ ├── select_seeds.py CoTracker3 시드 자동 선정
│ └── cotracker_seed_track.py CoTracker3 seed-driven 트래킹
│
├── merge_19node/ skeleton 17 + barbell 2 → 19-node
│ ├── merge_19node.py 19-node npy 배치 생성 (entry)
│ └── barbell_alignment.py 바벨 px → root-relative m 정합 (per-clip median scale)
│
├── action_recognition/ STGCN++ SSL 사전학습 + 5-fold FT·평가
│ ├── main.py · trainer.py · dataset.py · model.py · metrics.py
│ ├── ssl/scripts/hiclr_pretrain_stgcnpp.py HiCLR in-domain SSL
│ ├── make_19node_splits.py · window_extract_19node.py split·corpus 생성
│ └── auto_nlf_ssl_ft.sh · auto_nlf_ft_ramp.sh best-config 재현 스크립트
│
├── service/mesh_gs_poc/ SMPL-X mesh → gsplat 홀로그램 렌더
│ ├── gs_dual.py 정면·측면 dual-view 렌더 (메인)
│ ├── extract_faces.py SMPL-X face topology 추출 (1회 준비)
│ └── env.bat gsplat CUDA JIT 빌드 환경
│
├── app/ Streamlit 통합 데모
│ ├── app.py UI (업로드·trim·판정·결과·브리핑)
│ ├── configs/paths.py 경로·상수 단일 출처 (JERK5_* env)
│ └── pipeline/
│ ├── orchestrate.py run_pipeline — 단계 조율 + result 계약
│ ├── skeleton.py · barbell.py · merge_19node.py · gcn_inference.py
│ ├── mesh_viewer.py gsplat 홀로그램 호출 (env.bat subprocess)
│ └── llm_analysis.py Gemini 브리핑 (프롬프트는 prompts.py·비공개)
│
└── docs/ 실험 리포트 · 데이터 카드 · 참고문헌 · 데모 이미지
├── EXPERIMENTS_REPORT.md · DATA_CARD.md · REFERENCES.md
└── images/ 데모 스크린샷
각 폴더의 상세 구조·사용법은 해당 디렉토리의 README(skeleton/README.md, app/README.md 등)를 참고하세요. 저장소 루트에는 conda 환경 정의(environment-jerk5.yml, environment-jerk5-service.yml)와 LICENSE가 있습니다.
학습과 서비스는 서로 목적과 CUDA/torch 버전이 달라 conda 환경을 둘로 나눕니다.
각 환경은 저장소 루트의 environment-*.yml로 재현합니다(Windows + NVIDIA GPU 기준).
| 환경 | 용도 | 핵심 스택 |
|---|---|---|
jerk5 |
데이터 추출·학습 (skeleton·barbell·merge_19node·action_recognition) |
torch 2.1.2+cu118 · mmaction2 1.2.0 · mmcv 2.1.0 · ultralytics 8.4.33 |
jerk5-service |
통합 데모 (app·service) |
torch 2.6.0+cu124 · mmcv-lite 2.1.0 · gsplat 1.5.3 · streamlit 1.50.0 |
conda env create -f environment-jerk5.yml # 학습용
conda env create -f environment-jerk5-service.yml # 서비스용각 폴더의 requirements.txt는 pip 의존성만 따로 설치할 때 사용되며, 위 environment-*.yml이 전체 환경 재현(권장)입니다.
- 데이터 — Drive에서 NLF 좌표 데이터셋(아래 링크)을 받으면 학습을 바로 재현할 수 있습니다. 영상에서 직접 추출하려면
skeleton/(NLF 17-node 3D)과barbell/(바벨 2-node)로 각각 뽑은 뒤merge_19node/로 19-node를 병합합니다. 원본 영상은 저작권상 미포함입니다(docs/DATA_CARD.md). - 학습 —
action_recognition/auto_nlf_ssl_ft.sh(HiCLR SSL 사전학습) →action_recognition/auto_nlf_ft_ramp.sh(best config fine-tune). 단일 실행은action_recognition/main.py(--target-T,--angle-mode elbow_amplify_ramp등) 참고. - 서비스 — Drive에서 STGCN++ 체크포인트를 받아 배치한 뒤
app/에서 Streamlit 데모를 실행합니다(아래 실행 절).
학습 체크포인트와 데이터셋은 아래, Google Drive 링크에서 받아보실 수 있습니다.
- 모델 (STGCN++ SSL+FT, 5-fold): Download — 구성·로드법은
MANIFEST.txt참고 - 데이터셋 (NLF 좌표·바벨·메타, 영상 미포함): Download — 상세는
docs/DATA_CARD.md참고
배포에는 STGCN++ 판정 체크포인트만 포함됩니다.
| 모델 | 역할 | 포함 여부 | 라이선스 |
|---|---|---|---|
NLF (nlf_l_multi v0.3.2) |
영상 → 2D/3D skeleton | 미포함 (isarandi/nlf 배포) | 코드 MIT / 가중치 non-commercial |
| YOLO (fine-tuned) + CoTracker3 | 바벨 검출·추적 | weight 미포함 (추출 결과 barbell csv는 데이터셋에 포함) | YOLO 베이스 AGPL-3.0 |
| STGCN++ (SSL+FT) | 성공/실패 판정 | 포함 (위 Drive) | repo 라이선스 |
좌표·바벨 csv가 데이터셋에 포함되어 있어 STGCN 학습·판정 재현에는 NLF/YOLO weight가 필요하지 않습니다. 새 영상을 처음부터 처리할 때만 필요합니다.
cd app
conda activate jerk5-service # 위 '환경' 절에서 생성한 환경
# Drive에서 모델 체크포인트를 받아 배치한 뒤
streamlit run app.py --server.port 8502 # http://localhost:8502- Gemini 키는
.env의GEMINI_API_KEY로 사용합니다(.env.example복사 후 작성; 없으면 실패 브리핑만 생략). - 첫 접속 시 NLF 워밍업에 1~3분이 걸리고, 이후 분석은 warm 상태로 더욱 빠르게 사용할 수 있습니다.
- 외부 공유용 고정 URL은
app/start-tunnel.ps1(Cloudflare) 참고.
docs/EXPERIMENTS_REPORT.md— 실험 결과 요약 (backbone·SSL·barbell·angle 의사결정 흐름)docs/DATA_CARD.md— 데이터셋 출처·구조·라이선스·개인정보 등docs/REFERENCES.md— 참고 모델·논문 등
- 코드는 MIT(
LICENSE참고). 데이터는 비영리(연구·교육)이며, NLF·SMPL-X·YOLO 등 의존 모델은 각 원 라이선스를 별도로 확인하세요. - 데이터는 대한역도연맹(KWF) 공개 경기 영상에서 추출한 파생물이며, 연구·교육 목적의 비영리 사용을 전제로 합니다(상세:
docs/DATA_CARD.md).
이 저장소의 데모 그림에는 2025 IWF 세계선수권 대회 중계 영상의 스틸이 포함되어 있습니다. 원본은 IWF 공식 유튜브 채널에서 방송된 것으로, 모든 권리는 국제역도연맹(IWF)에 있습니다. 해당 스틸은 자세 추정 파이프라인의 출력을 데모용으로 보여주기 위해 스켈레톤/키포인트 오버레이를 입혀 비영리 학술·연구 목적으로만 사용했으며, 원본 영상에 대한 권리를 주장하지 않습니다. 권리자께서 이의가 있으시면 이슈로 남겨 주세요 — 문제 시, 즉시 삭제 조치하겠습니다.
The demonstration figures in this repository include still frames from the 2025 IWF World Weightlifting Championships (Førde, Norway), originally broadcast on the official IWF YouTube channel. All rights to the original footage belong to the International Weightlifting Federation (IWF). These stills are used solely for non-commercial academic and research purposes to illustrate the output of our pose-estimation pipeline, with a skeleton/keypoint overlay applied. We claim no ownership over the source material. If the rights holder objects to this use, please open an issue and the material will be removed promptly.





