1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| class VitalSignsExtractor: """ 生命体征提取 从雷达相位信号提取呼吸和心跳 """ def __init__(self, fps=30): self.fps = fps def extract(self, radar_frame_sequence): """ 提取生命体征 Args: radar_frame_sequence: 雷达帧序列 Returns: vital_signs: { 'breathing_rate': float, # 呼吸频率(次/分钟) 'heart_rate': float, # 心率(次/分钟) 'breathing_amplitude': float, 'heart_rate_amplitude': float } """ phase_signal = self._extract_phase(radar_frame_sequence) phase_signal = self._remove_motion_artifacts(phase_signal) breathing_signal = self._bandpass_filter( phase_signal, 0.1, 0.5, self.fps ) heart_signal = self._bandpass_filter( phase_signal, 0.8, 2.0, self.fps ) breathing_rate = self._extract_frequency(breathing_signal, self.fps) * 60 heart_rate = self._extract_frequency(heart_signal, self.fps) * 60 breathing_amplitude = np.std(breathing_signal) heart_amplitude = np.std(heart_signal) return { 'breathing_rate': breathing_rate, 'heart_rate': heart_rate, 'breathing_amplitude': breathing_amplitude, 'heart_rate_amplitude': heart_amplitude } def _extract_phase(self, radar_frames): """ 提取相位信号 胸部微动导致雷达信号相位变化 """ target_points = self._select_target_region(radar_frames) phase_sequence = [] for frame in radar_frames: phase = np.angle(frame['complex_data'][target_points]) phase_sequence.append(np.mean(phase)) phase_sequence = np.unwrap(phase_sequence) return np.array(phase_sequence) def _bandpass_filter(self, signal, low_freq, high_freq, fs): """ 带通滤波 """ from scipy import signal as sp_signal nyquist = fs / 2 low = low_freq / nyquist high = high_freq / nyquist b, a = sp_signal.butter(4, [low, high], btype='band') filtered = sp_signal.filtfilt(b, a, signal) return filtered def _extract_frequency(self, signal, fs): """ 频谱分析提取主频率 """ fft_result = np.fft.fft(signal) freqs = np.fft.fftfreq(len(signal), 1/fs) pos_freqs = freqs[:len(freqs)//2] pos_power = np.abs(fft_result[:len(fft_result)//2]) peak_idx = np.argmax(pos_power) main_freq = pos_freqs[peak_idx] return main_freq
|