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]) |