Spaces:
Runtime error
Runtime error
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]) |