resPyre is a comprehensive framework for estimating respiratory rate from video, using different methods and datasets.
The main script run_all.py supports:
- Extracting respiratory signals from videos using different methods
- Evaluating the results with multiple metrics
- Printing the evaluation metrics
python run_all.py -a <action> -d <results_dir>Arguments:
-a: Action to perform0: Extract respiratory signals1: Evaluate results2: Print metrics
-d: Directory to save/load results (default:results/)
The following methods are implemented:
- Deep Learning Methods:
- Motion-based Methods:
OF_Deep: Deep Optical Flow estimationOF_Model: Traditional Optical Flow (Farneback)DoF: Difference of Framesprofile1D: 1D Motion Profile
- rPPG-based Methods:
peak: Peak detectionmorph: Morphological analysisbss_ssa: Blind Source Separation with SSAbss_emd: Blind Source Separation with EMD
The code works with the following datasets:
- Extract respiratory signals using deep learning methods:
methods = [BigSmall(), MTTS_CAN()]
datasets = [BP4D(), COHFACE()]
extract_respiration(datasets, methods, "results/")- Evaluate the results:
python run_all.py -a 1 -d results/- Print metrics:
python run_all.py -a 2 -d results/To add a new dataset, create a class that inherits from DatasetBase and implement the required methods:
class NewDataset(DatasetBase):
def __init__(self):
super().__init__()
self.name = 'new_dataset' # Unique dataset identifier
self.path = self.data_dir + 'path/to/dataset/'
self.fs_gt = 1000 # Ground truth sampling frequency
self.data = []
def load_dataset(self):
# Load dataset metadata and populate self.data list
# Each item should be a dict with:
# - video_path: path to video file
# - subject: subject ID
# - chest_rois: [] (empty list, populated during processing)
# - face_rois: [] (empty list, populated during processing)
# - rppg_obj: [] (empty list, populated during processing)
# - gt: ground truth respiratory signal
def load_gt(self, trial_path):
# Load ground truth respiratory signal for a trial
pass
def extract_ROI(self, video_path, region='chest'):
# Extract ROIs from video for given region ('chest' or 'face')
pass
def extract_rppg(self, video_path, method='cpu_CHROM'):
# Extract rPPG signal from video
passTo add a new respiratory rate estimation method, inherit from MethodBase:
class NewMethod(MethodBase):
def __init__(self):
super().__init__()
self.name = 'new_method' # Unique method identifier
self.data_type = 'chest' # Input type: 'chest', 'face' or 'rppg'
def process(self, data):
# Implement respiratory signal extraction
# data contains:
# - chest_rois: list of chest ROI frames
# - face_rois: list of face ROI frames
# - rppg_obj: rPPG signal object
# - fps: video framerate
# Return the extracted respiratory signal
passAfter implementing the new classes, you can use them with the existing pipeline:
methods = [NewMethod()]
datasets = [NewDataset()]
extract_respiration(datasets, methods, "results/")Required packages are listed in requirements.txt. Key dependencies include:
- TensorFlow 2.2-2.4
- OpenCV
- SciPy
- NumPy
- Matplotlib
If you use this code, please cite the paper:
@article{boccignone2025remote,
title={Remote Respiration Measurement with RGB Cameras: A Review and Benchmark},
author={Boccignone, Giuseppe and Cuculo, Vittorio and D'Amelio, Alessandro and Grossi, Giuliano and Lanzarotti, Raffaella and Patania, Sabrina},
journal={ACM Computing Surveys},
year={2025},
publisher={ACM New York, NY}
}
This project is licensed under the GNU General Public License - see the LICENSE file for details.
