Phát hiện té ngã từ video dựa trên tư thế cơ thể
Project code hoàn chỉnh theo pipeline:
Video RGB → MediaPipe (33 điểm khớp) → chuẩn hóa tư thế → cửa sổ 4 giây → Pose-TCN/Pose-GRU → làm trơn → cảnh báo
Project đã chạy trên bộ UR Fall Detection (URFD). Kết quả cố định với seed 42 trên tập test gồm 41 cửa sổ thuộc 13 video:
| Mô hình | Accuracy | Precision | Recall | Specificity | F1 | ROC-AUC |
|---|---|---|---|---|---|---|
| Random Forest | 97,56% | 100,00% | 87,50% | 100,00% | 93,33% | 1,000 |
| Logistic Regression | 95,12% | 80,00% | 100,00% | 93,94% | 88,89% | 1,000 |
| Pose-TCN (CUDA) | 95,12% | 80,00% | 100,00% | 93,94% | 88,89% | 1,000 |
| Pose-GRU (CUDA) | 90,24% | 70,00% | 87,50% | 90,91% | 77,78% | 0,989 |
Đây là kết quả theo cửa sổ video, không phải theo người. URFD không cung cấp ánh xạ danh tính đủ rõ để chia subject-independent, vì vậy không dùng bảng trên để tuyên bố khả năng tổng quát hóa lâm sàng.
Chạy nhanh
Project dùng Python 3.10–3.12. Tạo môi trường và cài thư viện:
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
Để chạy Pose-GRU trên GPU NVIDIA, cài wheel PyTorch phù hợp trước. Máy đã dùng cho kết quả trong project chạy CUDA 12.8:
pip install torch --index-url https://download.pytorch.org/whl/cu128
python -c "import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))"
Chạy lại toàn bộ thí nghiệm URFD. Lệnh sẽ tự tải khoảng 70 video từ nguồn chính thức nếu chưa có dữ liệu:
python scripts/run_all.py
Chạy demo trên video:
python scripts/demo_video.py \
--input data/videos/fall/fall-01/fall-01-cam0.mp4 \
--model artifacts/experiments/urfd/pose_tcn/model.pt \
--output artifacts/demo_fall01.mp4
Chạy từng bước
# 1. Tải 30 video té và 40 video sinh hoạt thường ngày
python scripts/download_urfd.py
# 2. Trích keypoint và tạo dataset .npz
python scripts/prepare_dataset.py
# 3. Huấn luyện hai baseline
python scripts/train_baselines.py
# 4. Huấn luyện hai mô hình sâu
python scripts/train_gru.py
python scripts/train_tcn.py
# 5. Tổng hợp bảng và biểu đồ
python scripts/compare_models.py
# 6. Kiểm thử mã
pytest -q
Kết quả nằm tại artifacts/experiments/urfd/. Mỗi mô hình có trọng số, metrics.json, dự đoán từng mẫu, confusion matrix và ROC. File results.csv và model_comparison.png tổng hợp một lần chạy.
Dữ liệu riêng
Sắp xếp mỗi video trong một thư mục nhóm riêng. Nhóm có thể là mã người hoặc mã video; nếu có mã người, nên dùng mã người để phép chia không rò rỉ danh tính.
data/videos/
├── fall/
│ ├── person01/video01.mp4
│ └── person02/video02.mp4
└── normal/
├── person01/video03.mp4
└── person02/video04.mp4
Với dữ liệu không phải URFD và không có annotation frame, mọi cửa sổ trong fall/ được gán nhãn té. Nên cắt video để mỗi clip té thực sự chứa sự kiện té. Sửa tham số trong configs/default.yaml.
Thiết kế thí nghiệm
- Mỗi cửa sổ dài 40 frame ở 10 FPS, tương đương 4 giây; stride 10 frame.
- Pose được tịnh tiến về tâm hông và chia theo chiều dài thân/độ rộng vai.
- Pose-GRU dùng 140 chiều/frame: 33 ×
(x, y, z, visibility)và 8 đặc trưng hình học/chuyển động. - Pose-TCN dùng 60 chiều/frame: 13 khớp cốt lõi × 4 kênh và 8 đặc trưng bổ sung, giúp giảm overfit trên URFD nhỏ.
- Chia train/validation/test theo group với tỷ lệ 60/20/20; các cửa sổ cùng video luôn ở cùng tập.
- Ngưỡng xác suất tối ưu F1 chỉ được chọn trên validation. Test không tham gia chọn mô hình/ngưỡng.
- GRU và TCN dùng BCE có trọng số lớp, AdamW, early stopping; hai baseline dùng cùng dữ liệu và phép chia.
Chạy lặp nhiều seed
Lệnh sau chạy cả bốn mô hình với 5 seed, mỗi seed có phép chia theo video riêng. Pose-GRU và Pose-TCN tự dùng CUDA nếu có; hai mô hình scikit-learn chạy CPU.
python scripts/run_repeated_experiments.py --seeds 13 21 42 84 123 --device cuda
Kết quả từng lần nằm trong artifacts/experiments/urfd_repeated/seed_*/. Bảng tổng hợp mean, standard deviation, min và max nằm tại aggregate_results.csv.
Kết quả trên 5 seed đã chạy:
| Mô hình | Accuracy mean ± std | Recall mean ± std | F1 mean ± std | ROC-AUC mean ± std |
|---|---|---|---|---|
| Random Forest | 0,968 ± 0,026 | 0,885 ± 0,114 | 0,907 ± 0,061 | 0,997 ± 0,007 |
| Logistic Regression | 0,969 ± 0,021 | 0,955 ± 0,062 | 0,904 ± 0,095 | 0,991 ± 0,015 |
| Pose-TCN (CUDA) | 0,961 ± 0,040 | 0,915 ± 0,132 | 0,901 ± 0,069 | 0,983 ± 0,035 |
| Pose-GRU (CUDA) | 0,942 ± 0,043 | 0,865 ± 0,139 | 0,842 ± 0,098 | 0,996 ± 0,006 |
URFD có 70 chuỗi (30 fall, 40 ADL), phát hành theo CC BY-NC-SA 4.0 cho nghiên cứu phi thương mại tại trang dữ liệu chính thức. Khi sử dụng, trích dẫn bài của Kwolek và Kępski, DOI 10.1016/j.cmpb.2014.09.005.
Repository công khai chứa code, checkpoint và kết quả thí nghiệm. Video URFD gốc, pose dataset đã trích và video demo không được đóng gói cùng repository; dùng scripts/download_urfd.py để tải dữ liệu từ nguồn chính thức.