UdasriHasindu commited on
Commit ·
98a97f4
1
Parent(s): 66eca06
docs: complete doc
Browse files- README.md +158 -52
- gait2 (5).ipynb → gait.ipynb +0 -0
README.md
CHANGED
|
@@ -10,95 +10,201 @@ pinned: false
|
|
| 10 |
|
| 11 |
# Gait Analysis API
|
| 12 |
|
| 13 |
-
|
| 14 |
|
| 15 |
-
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
```
|
| 23 |
|
| 24 |
-
|
| 25 |
|
| 26 |
-
|
| 27 |
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
-
|
| 31 |
-
- form-data:
|
| 32 |
-
- `video`: video file
|
| 33 |
-
- `gender`: `male` or `female`
|
| 34 |
|
| 35 |
-
-
|
| 36 |
-
- `GET /health`
|
| 37 |
|
| 38 |
-
|
| 39 |
|
| 40 |
-
-
|
| 41 |
-
-
|
| 42 |
-
-
|
| 43 |
-
-
|
| 44 |
-
-
|
| 45 |
|
| 46 |
-
|
| 47 |
|
| 48 |
-
|
| 49 |
-
To prevent storage growth, use the cleanup script every 30 minutes.
|
| 50 |
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
-
- Deletes files older than 30 minutes (default)
|
| 58 |
-
- Removes empty subdirectories
|
| 59 |
|
| 60 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
```bash
|
| 63 |
-
|
| 64 |
```
|
| 65 |
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
```bash
|
| 69 |
-
|
| 70 |
```
|
| 71 |
|
| 72 |
-
|
| 73 |
|
| 74 |
-
|
|
|
|
|
|
|
| 75 |
|
| 76 |
-
|
| 77 |
|
| 78 |
-
-
|
| 79 |
-
-
|
| 80 |
-
-
|
| 81 |
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
- `PORT` (default: `7860`)
|
| 85 |
- `CLEANUP_INTERVAL_SECONDS` (default: `1800`)
|
| 86 |
- `RUNS_MAX_AGE_MINUTES` (default: `30`)
|
| 87 |
|
| 88 |
-
|
| 89 |
|
| 90 |
-
|
|
|
|
|
|
|
| 91 |
|
| 92 |
-
|
| 93 |
|
| 94 |
-
|
| 95 |
|
| 96 |
-
|
| 97 |
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
-
|
|
|
|
|
|
|
| 101 |
|
| 102 |
-
|
| 103 |
|
| 104 |
-
|
|
|
|
| 10 |
|
| 11 |
# Gait Analysis API
|
| 12 |
|
| 13 |
+
Clinical gait analysis service built with FastAPI, OpenCV, and MediaPipe Pose.
|
| 14 |
|
| 15 |
+
It processes a front-view walking video and returns:
|
| 16 |
|
| 17 |
+
- extracted gait biomarkers
|
| 18 |
+
- rule-based clinical interpretation
|
| 19 |
+
- overall gait stability score
|
| 20 |
+
- annotated skeleton video
|
| 21 |
+
- clinical dashboard plot
|
|
|
|
| 22 |
|
| 23 |
+
The notebook prototype is kept in [gait.ipynb](<gait.ipynb>), and the production API implementation is in [app.py](app.py).
|
| 24 |
|
| 25 |
+
## Table of contents
|
| 26 |
|
| 27 |
+
- Overview
|
| 28 |
+
- Project structure
|
| 29 |
+
- How it works
|
| 30 |
+
- API reference
|
| 31 |
+
- Local development
|
| 32 |
+
- Docker usage
|
| 33 |
+
- Storage cleanup strategy
|
| 34 |
+
- Hugging Face Spaces deployment
|
| 35 |
+
- GitHub Actions auto-deploy
|
| 36 |
+
- Troubleshooting
|
| 37 |
|
| 38 |
+
## Overview
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
+
This API is designed for single-video gait assessment.
|
|
|
|
| 41 |
|
| 42 |
+
Core stack:
|
| 43 |
|
| 44 |
+
- FastAPI for REST endpoints
|
| 45 |
+
- MediaPipe Pose for landmark extraction
|
| 46 |
+
- OpenCV for video I/O and skeleton overlay
|
| 47 |
+
- NumPy/SciPy for signal processing and feature extraction
|
| 48 |
+
- Matplotlib for biomarker visualizations
|
| 49 |
|
| 50 |
+
Dependencies are listed in [requirements.txt](requirements.txt).
|
| 51 |
|
| 52 |
+
## Project structure
|
|
|
|
| 53 |
|
| 54 |
+
- [app.py](app.py): Main API + gait analysis pipeline
|
| 55 |
+
- [requirements.txt](requirements.txt): Python dependencies
|
| 56 |
+
- [Dockerfile](Dockerfile): Container build (HF Spaces compatible)
|
| 57 |
+
- [scripts/start.sh](scripts/start.sh): Container startup + background cleanup loop
|
| 58 |
+
- [scripts/cleanup_runs.py](scripts/cleanup_runs.py): Deletes old generated files
|
| 59 |
+
- [.github/workflows/deploy-hf-space.yml](.github/workflows/deploy-hf-space.yml): Auto-sync GitHub repo to HF Space
|
| 60 |
+
- [gait.ipynb](<gait.ipynb>): Original notebook source logic
|
| 61 |
|
| 62 |
+
## How it works
|
| 63 |
|
| 64 |
+
High-level flow:
|
| 65 |
+
|
| 66 |
+
1. Upload `video` + `gender`
|
| 67 |
+
2. Extract pose landmarks for each frame
|
| 68 |
+
3. Validate video (person detected, front-view check)
|
| 69 |
+
4. Build temporal signals (ankles, feet, arm swing, hip center)
|
| 70 |
+
5. Smooth + detrend + detect peaks
|
| 71 |
+
6. Compute biomarkers (`stride_variability`, `cadence`, `symmetry_ratio`, arm metrics)
|
| 72 |
+
7. Create clinical interpretation text
|
| 73 |
+
8. Compute weighted gait stability score
|
| 74 |
+
9. Generate dashboard image + annotated video
|
| 75 |
+
10. Return JSON payload
|
| 76 |
+
|
| 77 |
+
Main endpoints are declared in [app.py](app.py#L560-L785).
|
| 78 |
+
|
| 79 |
+
## API reference
|
| 80 |
+
|
| 81 |
+
### `GET /`
|
| 82 |
+
|
| 83 |
+
Basic API metadata and endpoint hints.
|
| 84 |
+
|
| 85 |
+
### `POST /analyze`
|
| 86 |
+
|
| 87 |
+
Accepts multipart form-data:
|
| 88 |
+
|
| 89 |
+
- `video`: gait video (`mp4/mov/avi/...`)
|
| 90 |
+
- `gender`: `male` or `female`
|
| 91 |
+
|
| 92 |
+
Returns analysis JSON with base64-embedded files (`annotated_video`, `clinical_dashboard`).
|
| 93 |
+
|
| 94 |
+
Use this when you want everything in one response.
|
| 95 |
+
|
| 96 |
+
### `POST /analyze_files`
|
| 97 |
+
|
| 98 |
+
Accepts multipart form-data:
|
| 99 |
+
|
| 100 |
+
- `video`: gait video
|
| 101 |
+
- `gender`: `male` or `female`
|
| 102 |
+
|
| 103 |
+
Returns analysis JSON with downloadable URLs:
|
| 104 |
+
|
| 105 |
+
- `/download/{session_id}_annotated.mp4`
|
| 106 |
+
- `/download/{session_id}_dashboard.png`
|
| 107 |
+
|
| 108 |
+
This is generally the better choice for deployment because responses stay smaller than full base64 payloads.
|
| 109 |
+
|
| 110 |
+
### `GET /download/{filename}`
|
| 111 |
+
|
| 112 |
+
Downloads generated output files from `runs/outputs`.
|
| 113 |
+
|
| 114 |
+
### `GET /health`
|
| 115 |
+
|
| 116 |
+
Simple health check.
|
| 117 |
|
|
|
|
|
|
|
| 118 |
|
| 119 |
+
## Local development
|
| 120 |
+
|
| 121 |
+
1. Create environment and install dependencies
|
| 122 |
+
|
| 123 |
+
```bash
|
| 124 |
+
python -m venv .venv
|
| 125 |
+
source .venv/bin/activate
|
| 126 |
+
pip install -r requirements.txt
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
2. Run API
|
| 130 |
|
| 131 |
```bash
|
| 132 |
+
uvicorn app:app --reload --host 0.0.0.0 --port 8000
|
| 133 |
```
|
| 134 |
|
| 135 |
+
3. Open docs
|
| 136 |
+
|
| 137 |
+
- Swagger UI: http://127.0.0.1:8000/docs
|
| 138 |
+
- ReDoc: http://127.0.0.1:8000/redoc
|
| 139 |
+
|
| 140 |
+
## Docker usage
|
| 141 |
+
|
| 142 |
+
Build:
|
| 143 |
|
| 144 |
```bash
|
| 145 |
+
docker build -t gait-api:latest .
|
| 146 |
```
|
| 147 |
|
| 148 |
+
Run:
|
| 149 |
|
| 150 |
+
```bash
|
| 151 |
+
docker run --rm -p 7860:7860 gait-api:latest
|
| 152 |
+
```
|
| 153 |
|
| 154 |
+
Container defaults:
|
| 155 |
|
| 156 |
+
- serves on port `7860`
|
| 157 |
+
- startup script: [scripts/start.sh](scripts/start.sh)
|
| 158 |
+
- output directory: `/app/runs/outputs`
|
| 159 |
|
| 160 |
+
## Storage cleanup strategy
|
| 161 |
+
|
| 162 |
+
Generated files from `/analyze_files` are stored under `runs/outputs`.
|
| 163 |
+
|
| 164 |
+
Cleanup is handled by [scripts/cleanup_runs.py](scripts/cleanup_runs.py):
|
| 165 |
+
|
| 166 |
+
- default retention: 30 minutes
|
| 167 |
+
- deletes old files under `runs/`
|
| 168 |
+
- preserves required directory structure
|
| 169 |
+
|
| 170 |
+
In Docker/HF Spaces, [scripts/start.sh](scripts/start.sh) starts a background cleanup loop automatically.
|
| 171 |
+
|
| 172 |
+
Configurable environment variables:
|
| 173 |
|
|
|
|
| 174 |
- `CLEANUP_INTERVAL_SECONDS` (default: `1800`)
|
| 175 |
- `RUNS_MAX_AGE_MINUTES` (default: `30`)
|
| 176 |
|
| 177 |
+
Optional manual run:
|
| 178 |
|
| 179 |
+
```bash
|
| 180 |
+
python scripts/cleanup_runs.py --path ./runs --max-age-minutes 30 --dry-run
|
| 181 |
+
```
|
| 182 |
|
| 183 |
+
## Hugging Face Spaces deployment (Docker)
|
| 184 |
|
| 185 |
+
This repository is configured for Docker Spaces.
|
| 186 |
|
| 187 |
+
Key points:
|
| 188 |
|
| 189 |
+
- README front matter is required and already included
|
| 190 |
+
- container uses [Dockerfile](Dockerfile)
|
| 191 |
+
- app starts via [scripts/start.sh](scripts/start.sh)
|
| 192 |
+
- `PORT` env is respected (default `7860`)
|
| 193 |
+
|
| 194 |
+
Recommended endpoint on Spaces:
|
| 195 |
+
|
| 196 |
+
- Use `/analyze_files` for better response size and reliability
|
| 197 |
+
|
| 198 |
+
## GitHub Actions auto-deploy to HF Space
|
| 199 |
+
|
| 200 |
+
Workflow: [.github/workflows/deploy-hf-space.yml](.github/workflows/deploy-hf-space.yml)
|
| 201 |
+
|
| 202 |
+
Behavior:
|
| 203 |
|
| 204 |
+
- triggers on push to `main`
|
| 205 |
+
- sanitizes `HF_TOKEN`
|
| 206 |
+
- force-pushes repository to `xplorers/GAIT_API`
|
| 207 |
|
| 208 |
+
Required GitHub secret:
|
| 209 |
|
| 210 |
+
- `HF_TOKEN`: Hugging Face token with write access to the target Space
|
gait2 (5).ipynb → gait.ipynb
RENAMED
|
File without changes
|