MMESA-ZeroGPU / tabs /heart_rate_variability.py
vitorcalvi's picture
pre-launch
efabbbd
raw
history blame
2.32 kB
import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
import tempfile
import cv2
from scipy.signal import find_peaks, butter, filtfilt
def extract_ppg_signal(video_file):
cap = cv2.VideoCapture(video_file)
ppg_signal = []
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
ppg_signal.append(np.mean(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)))
cap.release()
return np.array(ppg_signal)
def process_ppg_signal(ppg_signal, fs=30):
nyquist = 0.5 * fs
b, a = butter(1, [0.5 / nyquist, 3.0 / nyquist], btype='band')
return filtfilt(b, a, ppg_signal)
def detect_hrv(video_file):
filtered_signal = process_ppg_signal(extract_ppg_signal(video_file))
peaks, _ = find_peaks(filtered_signal, distance=15) # 30 fps / 2.5
rr_intervals = np.diff(peaks) / 30
heart_rate = 60 / rr_intervals.mean()
hrv = np.std(rr_intervals)
plt.figure(figsize=(10, 4))
time = np.arange(len(filtered_signal)) / 30
plt.plot(time, filtered_signal, label='Filtered PPG Signal')
plt.plot(time[peaks], filtered_signal[peaks], 'ro', label='Detected Peaks')
plt.title('Heart Rate Variability over Time')
plt.xlabel('Time (s)')
plt.ylabel('PPG Signal Intensity')
plt.legend()
plt.tight_layout()
with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as temp_file:
plt.savefig(temp_file.name)
plt.close()
return f"{hrv:.2f} ms", f"{heart_rate:.2f} BPM", temp_file.name
def create_hrv_tab():
with gr.Row():
with gr.Column(scale=2):
input_video = gr.Video(label="Input Video")
with gr.Row():
clear_btn = gr.Button("Clear", scale=1)
submit_btn = gr.Button("Analyze", scale=1, elem_classes="submit")
with gr.Column(scale=1):
output_hrv = gr.Label(label="HRV Value")
output_hr = gr.Label(label="Average Heart Rate")
output_plot = gr.Image(label="HRV Plot")
submit_btn.click(detect_hrv, inputs=[input_video], outputs=[output_hrv, output_hr, output_plot], queue=True)
clear_btn.click(lambda: (None, None, None, None), outputs=[input_video, output_hrv, output_hr, output_plot], queue=True)
gr.Examples(["./assets/videos/fitness.mp4"], [input_video])