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.
