--- license: cc-by-nc-sa-4.0 language: - vi library_name: pytorch pipeline_tag: video-classification tags: - computer-vision - fall-detection - pose-estimation - mediapipe - temporal-convolution --- # 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: ```bash 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: ```bash 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: ```bash python scripts/run_all.py ``` Chạy demo trên video: ```bash 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 ```bash # 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. ```text 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](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. ```bash 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](https://fenix.ur.edu.pl/~mkepski/ds/uf.html). 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.