This project provides a machine learning pipeline to estimate Systolic (SBP) and Diastolic (DBP) blood pressure from Photoplethysmogram (PPG) signals extracted from smartphone videos. It implements both a feature-engineered Random Forest (RF) baseline and a deep learning 1D Convolutional Neural Network (CNN).
- Python 3.12+
- NVIDIA GPU (Recommended for CNN training and inference)
- uv (Recommended for dependency management)
Clone the repository and install dependencies using uv:
uv pip install -r requirements.txtTrain the models on the UCI dataset parts. The script auto-detects available hardware (CUDA/MPS/CPU).
# Train Random Forest (CPU-based)
uv run python train.py --model rf --parts 1 2 3 4
# Train 1D CNN (Hardware-accelerated)
uv run python train.py --model cnn --parts 1 2 3 4 --epochs 100Predict blood pressure from a recorded video:
# Default prediction using Random Forest
uv run python predict.py your_video.mp4
# Prediction using CNN (Recommended for accuracy)
uv run python predict.py your_video.mp4 --model cnnThe models were evaluated on the UCI Cuff-less Blood Pressure Estimation dataset.
| Metric | Random Forest | 1D CNN |
|---|---|---|
| SBP MAE | 13.91 mmHg | 7.50 mmHg |
| DBP MAE | 6.67 mmHg | 4.18 mmHg |
| SBP R2 | 0.24 | 0.70 |
| DBP R2 | 0.56 | 0.74 |
| Hardware | CPU | GPU (CUDA/MPS) |
The system includes a calibration mechanism to personalize predictions using reference measurements from clinical devices. This accounts for individual physiological variations and model biases.
# Calibrate model with a reference BP reading
uv run python predict.py video.mp4 --calibrate --sbp 120 --dbp 80 --model cnn
# View current calibration status
uv run python predict.py --show-calibration
# Clear all stored calibration data
uv run python predict.py --clear-calibrationThe CNN model processes raw PPG signals through a series of convolutional layers designed for temporal feature extraction:
- Input: (1, 625) normalized PPG signal
- Layers:
- Conv1D (32 filters, kernel=7) + BatchNorm + ReLU + MaxPool
- Conv1D (64 filters, kernel=5) + BatchNorm + ReLU + MaxPool
- Conv1D (128 filters, kernel=3) + BatchNorm + ReLU + MaxPool
- Conv1D (128 filters, kernel=3) + BatchNorm + ReLU
- GlobalAveragePooling1D
- Fully Connected (128) + ReLU + Dropout (0.3)
- Fully Connected (64) + ReLU + Dropout (0.3)
- Output: Fully Connected (2) -> [SBP, DBP]
- Parameters: ~110K trainable weights
- Windowing: 5-second segments at 125 Hz (625 samples per window)
- Filtering: Butterworth Bandpass filter (0.5–8.0 Hz)
- Normalization: StandardScaler applied per signal (CNN) or per feature (RF)
- Video Processing: Automatic color channel selection based on signal-to-noise ratio; resampling from camera FPS to 125 Hz.
The project utilizes PyTorch for the CNN implementation and automatically detects the best available backend:
- CUDA: NVIDIA GPUs (via
cuda) - MPS: Apple Silicon GPUs (via
mps) - CPU: Standard fallback for all systems
src/: Core implementation modulesmodel_cnn.py: CNN architecture and inference logicmodel_trainer.py: Random Forest training orchestrationmodel_trainer_cnn.py: CNN training orchestrationdata_loader.py: UCI dataset parsing and windowingfeatures.py: PPG feature extraction using NeuroKit2calibration.py: Persistent calibration managementinference_video.py: End-to-end video-to-BP pipeline
model/: Directory for saved model weights and metadatauci_dataset/: Target directory for .mat data filestrain.py: CLI for model trainingpredict.py: CLI for running inference on video files
- UCI Cuff-less Blood Pressure Estimation Dataset: Archive Link
- Signal analysis facilitated by NeuroKit2