| # Data record |
|
|
| ## Model training data |
|
|
| The XGBoost classifier is trained on the **engineered feature dataset** derived upstream from a merged image collection. The image collection itself is **upstream and out of scope** for the classifier β at training the classifier sees the CSV loaded as a 56-column DataFrame; at inference it sees a 56-column DataFrame built by `scripts/run.py` from an upstream 51+bbox DataFrame. |
|
|
| ### Upstream image collection (used only to generate the feature CSV) |
|
|
| - **Data collector / dataset owner:** Curated from public Roboflow Universe datasets (Hong Nguyα»
n, Ludovico Valenti, Final Year Project, and IIUI Impact). |
| - **Dataset version or snapshot:** Combined Snapshot v1. |
| - **Annotation format (upstream)**: YOLO / Roboflow Object Detection format. |
| - **Curation notes:** Source datasets were merged, deduplicated, and balanced to eliminate class bias. |
| - **Upstream links / references:** |
| - [Hong Nguyα»
n - fall_detection-8vxyk (v4)](https://universe.roboflow.com/hong-nguyn-lixag/fall_detection-8vxyk/dataset/4) |
| - [Ludovico Valenti - fall-stand-4pvxw (v2)](https://universe.roboflow.com/ludovico-valenti-nqvcr/fall-stand-4pvxw/dataset/2) |
| - [Final Year Project - human-fall (v2)](https://universe.roboflow.com/final-year-project-i0ziv/human-fall/dataset/2) |
| - [IIUI Impact - human-fall-detection-hgjus (v5)](https://universe.roboflow.com/iiui-impct/human-fall-detection-hgjus/dataset/5) |
|
|
| --- |
|
|
| ## Dataset counts and split summary (upstream image counts) |
|
|
| ### Overall sample count & class distribution |
|
|
| | Class | Sample count | Percentage | |
| | --- | ---: | ---: | |
| | Fall (`fall` / `fall-detected` / `sitting` ) | 23,300 | 50.0% | |
| | Normal (`normal` / `standing` / `walking`) | 23,300 | 50.0% | |
| | **Total** | **46,600** | **100.0%** | |
|
|
| ### Train / Validation / Test split breakdown |
|
|
| | Split | Fall samples | Normal samples | Total split count | Percentage | |
| | --- | ---: | ---: | ---: | ---: | |
| | **Train** | 16,310 | 16,310 | 32,620 | 70.0% | |
| | **Validation** | 4,660 | 4,660 | 9,320 | 20.0% | |
| | **Test** | 2,330 | 2,330 | 4,660 | 10.0% | |
| | **Total** | **23,300** | **23,300** | **46,600** | **100.0%** | |
|
|
| --- |
|
|
| ## Benchmark & evaluation sources (upstream) |
|
|
| | Source Dataset | Upstream Version | Local File Format | Primary Classes Tracked | |
| | --- | --- | --- | --- | |
| | Hong Nguyα»
n | v4 | JPG / TXT (YOLO) | Fall, Non-Fall | |
| | Ludovico Valenti | v2 | JPG / TXT (YOLO) | Fall, Stand | |
| | Final Year Project | v2 | JPG / TXT (YOLO) | Human Fall | |
| | IIUI Impact | v5 | JPG / TXT (YOLO) | Fall-Detected, Sitting, Walking, Standing | |
|
|
| --- |
|
|
| ## Independent validation data |
|
|
| Hold-off validation datasets reserved for independent testing must remain outside the repository commit tree. The evaluator must record the source window, camera angles, sampling rate, and license permissions prior to benchmark execution. |
|
|
| --- |
|
|
| # Data Record: Extracted Pose Benchmark Dataset (Classifier Training Data) |
|
|
| This document records the specifications for the CSV dataset that directly trains the XGBoost classifier (`pose_benchmark_priority1_dataset.csv`). At **training time** the CSV is loaded into a pandas DataFrame; at **inference time** upstream delivers a DataFrame of **51 features + bbox** and `scripts/run.py` computes the 5 features in memory (no CSV into the model). |
|
|
| **Inference input contract (what goes IN to `run.py`):** |
|
|
| | Columns | Count | Source | |
| | --- | ---: | --- | |
| | `x_i, y_i, conf_i` for i = 0β¦16 | **51** | Upstream (input contract) | |
| | `x1, y1, x2, y2` | 4 | Upstream bbox (needed to compute the 5) | |
| | | **55** | **Total input to `run.py`** | |
|
|
| The **extra 5 features are extracted in `run.py`**, not received. Model input after extraction = **56 = 51 + 5**. |
|
|
| ``` |
| TRAINING: CCTV IMAGE β YOLO26x-Pose β 51 features β +5 β CSV (56 features + split + label) β DataFrame β XGBoost |
| INFERENCE: upstream DataFrame (51 + bbox, 55 cols) β run.py: +5 β 56-col DataFrame β XGBoost (no CSV into model) |
| ``` |
|
|
| --- |
|
|
| ## 1. Primary Dataset Summary |
|
|
| * **Dataset Name / Export Path:** `pose_benchmark_priority1_dataset.csv` |
| * **Upstream Image Directory (for generation only):** `/home/ctspl/model_training/fall/version2/fall_no_fall_data` |
| * **Extractor Architecture (upstream, not part of classifier):** `yolo26x-pose.pt` (Ultralytics YOLO Pose Estimation) |
| * **Confidence Cutoff (`CONF_THRESH` for NaN masking):** `0.25` (training generation) / `0.50` (inference threshold) |
| * **Label Mapping:** |
| * `0`: Normal / Non-Fall |
| * `1`: Fall |
| * **Direct XGBoost Input**: 56-column pandas DataFrame (one row per person) = 51 normalized keypoint features (17 Γ 3) + 5 Priority 1 features. No image data; no CSV into the model at inference. |
| * **Feature Scope:** 17 COCO keypoints normalized to bounding box + 5 Priority 1 CCTV-invariant features. Each row = one person. |
| |
| > The system will (upstream of XGBoost): 1) Extract 17 keypoints per person using YOLO-Pose (51 features), 2) Calculate 56 features total per person (51 normalized + 5 Priority 1) β the 56-vector is the direct XGBoost input. Older docs described this as β58 features (52 + 5)β; correct count is 56 = 51 (17Γ3) + 5. Total CSV columns = 58 (56 features + `split` + `label`). |
| |
| --- |
| |
| ## 2. Feature Schema & Column Definitions |
| |
| The generated CSV contains **56 feature columns **. |
| |
| ### A. Normalized Keypoint Features (Columns 1 β 51) |
| |
| 17 COCO keypoints Γ 3 values (`x_norm`, `y_norm`, `confidence`) where `x_norm = (x - x1) / w`, `y_norm = (y - y1) / h` relative to the person's bounding box. Low-confidence keypoints have `x_norm`/`y_norm` = `NaN` (confidence preserved). Order matches COCO indexing (0=nose β¦ 16=right ankle). Header: `x_0,y_0,conf_0,...,x_16,y_16,conf_16`. |
| |
| ### B. Priority 1 CCTV-Invariant Features (Columns 52 β 56) β total 5 |
| |
| 1. **`aspect_ratio`** (col 52): Bounding box proportion `w / h`. High values indicate horizontal body orientation (falling/lying). |
| 2. **`nose_relative_y`** (col 53): Normalized vertical height of the nose: |
| $$\text{nose\_relative\_y} = \frac{Y_{\text{nose}} - Y_1}{h}$$ |
| 3. **`torso_angle`** (col 54): Angle of the torso vector (Hip Midpoint β Shoulder Midpoint) relative to vertical Y-axis: |
| $$\theta = \text{atan2}(|\Delta X|, |\Delta Y|) \times \frac{180}{\pi}$$ |
| 4. **`norm_com_y`** (col 55): Vertical Center of Mass normalized across visible keypoints weighted by confidence: |
| $$\text{norm\_com\_y} = \frac{\sum (Y_i \times c_i) / \sum c_i - Y_1}{h}$$ |
| 5. **`head_hip_v_dist`** (col 56): Vertical normalized distance between hips and head/nose: |
| $$\text{head\_hip\_v\_dist} = \frac{Y_{\text{hip\_mid}} - Y_{\text{nose}}}{h}$$ |
|
|
| --- |
|
|
| ### C. Dataset Metadata & Supervision (Columns 57 β 58) β not model input |
|
|
| * **`split`**: Source split identifier (`train`, `val`, or `test`). |
| * **`label`**: Binary target label (`0` for Normal, `1` for Fall). |
|
|
| For training/evaluation, the classifier uses only columns 1β56 as `X` (a **56-column DataFrame**) and `label` as `y` (see `scripts/train.py:70`). At inference, upstream provides the 51 keypoint columns + bbox as a DataFrame; `scripts/run.py` computes columns 52β56 and passes the resulting 56-column DataFrame to `predict_proba`. |
|
|
| --- |
|
|