Skip to main content

Quick Start

This guide will help you run your first vital signs measurement in just a few minutes.

Prerequisites

Ensure you have Python 3.8 or higher installed on your system

Installation

1

Clone the repository

git clone https://github.com/your-org/evm-vital-signs-monitor.git
cd evm-vital-signs-monitor
2

Install dependencies

pip install -r requirements.txt
This installs all required packages including OpenCV, NumPy, SciPy, MediaPipe, and Ultralytics.
Installation may take 5-10 minutes depending on your internet connection.
3

Verify installation

python -c "import cv2, mediapipe, numpy; print('All dependencies installed successfully!')"

Your First Measurement

Let’s run a simple example that detects faces in a video and estimates heart rate.
1

Navigate to experiments folder

cd Python/experiments
2

Run the simple ROI detection example

python simple_run_ROI.py
This script benchmarks face detection performance and measures FPS.

Understanding the Output

The script will display real-time metrics:
Video: /path/to/video.mp4
Frames totales: 10800, FPS original: 30.0
--------------------------------------------------
Frame 200: Tiempo detección: 25.3ms, FPS: 39.5
Frame 400: Tiempo detección: 24.8ms, FPS: 40.3
...

Running EVM Processing

Now let’s extract vital signs using Eulerian Video Magnification:
import cv2
import sys
import os
from collections import deque
import numpy as np

# Add project root to path
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)

from src.face_detector.manager import FaceDetector
from src.evm.evm_manager import process_video_evm_vital_signs
from src.config import TARGET_ROI_SIZE

def measure_vital_signs(video_path, buffer_size=200):
    """Extract heart rate and respiratory rate from video."""
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print(f"Error: Could not open {video_path}")
        return
    
    # Initialize face detector
    face_detector = FaceDetector(model_type='mediapipe')
    frame_buffer = []
    hr_history = deque(maxlen=10)
    
    print("Processing video...")
    
    try:
        while True:
            ret, frame = cap.read()
            if not ret:
                break
            
            # Detect face and extract ROI
            roi = face_detector.detect_face(frame)
            
            if roi:
                x, y, w, h = roi
                roi_frame = frame[y:y+h, x:x+w]
                roi_frame = cv2.resize(roi_frame, TARGET_ROI_SIZE)
                frame_buffer.append(roi_frame)
                
                # Process when buffer is full
                if len(frame_buffer) >= buffer_size:
                    result = process_video_evm_vital_signs(frame_buffer)
                    
                    hr = result['heart_rate']
                    rr = result['respiratory_rate']
                    
                    if hr is not None:
                        hr_history.append(hr)
                        filtered_hr = np.median(list(hr_history))
                        print(f"Heart Rate: {filtered_hr:.1f} BPM")
                    
                    if rr is not None:
                        print(f"Respiratory Rate: {rr:.1f} BPM")
                    
                    frame_buffer.clear()
    
    finally:
        cap.release()
        face_detector.close()
        print("Processing complete!")

if __name__ == "__main__":
    # Replace with your video file path
    measure_vital_signs("path/to/your/video.mp4")

Expected Output

When running the EVM processing script, you’ll see output like:
======================================================================
PROCESAMIENTO CON EULERIAN VIDEO MAGNIFICATION (EVM)
======================================================================
Video: dataset_2/subject1/vid.mp4
Frames totales: 10800, FPS original: 30.0
Tamaño de buffer: 200 frames
======================================================================

Chunk 1 (frames 1-200):
  Tiempo chunk: 1.85s | Tiempo/frame: 9.3ms | FPS: 108.1
  HR estimada: 78.2 BPM | GT: 80.1 BPM | Error: -1.9 BPM

Chunk 2 (frames 201-400):
  Tiempo chunk: 1.92s | Tiempo/frame: 9.6ms | FPS: 104.2
  HR estimada: 79.5 BPM | GT: 79.8 BPM | Error: -0.3 BPM
Each “chunk” represents 200 frames (approximately 6.7 seconds at 30 FPS). The system needs this duration to accurately estimate vital signs via frequency analysis.

Understanding the Results

The output includes several key metrics:
  • Tiempo chunk: Total processing time for 200 frames
  • Tiempo/frame: Average time per frame (lower is better)
  • FPS: Effective processing frame rate
  • HR estimada: Estimated heart rate in beats per minute
  • RR estimada: Estimated respiratory rate in breaths per minute
  • Filtered using median of last 10 measurements for stability
  • GT: Ground truth value from reference device
  • Error: Difference between estimate and ground truth (positive = overestimate)

Run Complete Benchmark

For comprehensive performance analysis including detection, EVM processing, and accuracy:
python simple_run_EVM_ROI.py
This runs an end-to-end benchmark that measures:
  1. Face detection performance (ROI extraction)
  2. EVM processing time (vital signs extraction)
  3. End-to-end pipeline (combined metrics)
  4. Accuracy statistics (compared to ground truth)

Benchmark Output

================================================================================
1. MÉTRICAS DE DETECCIÓN FACIAL (ROI)
--------------------------------------------------------------------------------
Frames procesados: 10800
Tiempo promedio por frame: 25.1 ms
FPS de detección: 39.8

2. MÉTRICAS DE PROCESAMIENTO EVM
--------------------------------------------------------------------------------
Chunks procesados: 54
Tiempo promedio por frame: 9.5 ms
FPS de procesamiento EVM: 105.3

3. MÉTRICAS END-TO-END (DETECCIÓN + EVM)
--------------------------------------------------------------------------------
FPS end-to-end: 28.7
Tiempo por medición: 6.97s (200 frames)

Desglose de tiempo promedio:
  Detección ROI: 73.2%
  Procesamiento EVM: 26.8%

4. MÉTRICAS DE PRECISIÓN (HEART RATE)
--------------------------------------------------------------------------------
Número de mediciones: 54

Métricas de Error:
  Mean Absolute Error (MAE): 3.42 BPM
  Root Mean Square Error (RMSE): 4.18 BPM
  
Distribución de Errores:
  Dentro de ±5 BPM: 87.0%
  Dentro de ±10 BPM: 96.3%

Correlación con Ground Truth: 0.924
Good performance indicators:
  • MAE < 5 BPM for heart rate
  • 85% of predictions within ±5 BPM
  • Correlation > 0.9 with ground truth
  • Detection FPS > 30 for real-time capability

Choosing a Different Face Detector

You can easily switch between detection models by changing the model_type parameter:
face_detector = FaceDetector(model_type='mediapipe')
# Fast and accurate - best for Raspberry Pi
# ~30-40 FPS on RPi 4
See Choosing a Detector for detailed comparison and recommendations.

Using Your Own Video

To process your own video file:
  1. Prepare your video:
    • 30 FPS recommended (adjustable in src/config.py)
    • Clear view of face
    • Stable lighting
    • Minimal head movement
  2. Update the video path in the script:
    VIDEO_PATH = "/path/to/your/video.mp4"
    
  3. For webcam input, use:
    cap = cv2.VideoCapture(0)  # 0 for default webcam
    
For accurate measurements:
  • Ensure stable lighting (avoid flickering or rapid changes)
  • Keep subject relatively still
  • Minimum 200 frames needed per measurement (~6.7 seconds at 30 FPS)
  • Indoor environments work best

Next Steps

Installation Guide

Detailed setup for Docker, virtual environments, and Raspberry Pi

Configuration

Customize amplification factors, filters, and processing parameters

Understanding EVM

Learn how the algorithm extracts vital signs

Performance Optimization

Tips for improving speed and accuracy

Troubleshooting

  • Ensure adequate lighting
  • Check that face is clearly visible in frame
  • Try a different detection model
  • Verify camera/video source is working
  • Check for stable lighting conditions
  • Ensure subject remains still
  • Verify proper camera focus
  • Try adjusting amplification factors in src/config.py
  • Increase buffer size for more stable estimates
  • Switch to MediaPipe or Haar detector
  • Reduce pyramid levels in config (for RPi)
  • Lower TARGET_ROI_SIZE in src/config.py
  • Consider using Docker image with optimized dependencies
  • Verify all dependencies installed: pip install -r requirements.txt
  • Check Python version (3.8+ required)
  • Ensure you’re in the correct directory
  • Try creating a fresh virtual environment

Build docs developers (and LLMs) love