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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
| import numpy as np from scipy.signal import butter, filtfilt, find_peaks
class CPDDetector: """ 儿童存在检测器 """ def __init__(self, config): self.config = config self.range_fft_size = 256 self.doppler_fft_size = 64 def process_frame(self, adc_data): """ 处理单帧数据 Args: adc_data: ADC数据 (chirps, samples) Returns: detection: 检测结果 """ range_fft = np.fft.fft(adc_data, n=self.range_fft_size, axis=1) doppler_fft = np.fft.fft(range_fft, n=self.doppler_fft_size, axis=0) detections = self.cfar_detector(np.abs(doppler_fft)) clusters = self.cluster_detections(detections) vital_signs = self.extract_vital_signs(clusters) return { "occupancy": len(clusters) > 0, "vital_signs": vital_signs, "classification": self.classify(clusters, vital_signs) } def extract_vital_signs(self, clusters): """ 提取生命体征(呼吸、心跳) Args: clusters: 检测到的目标簇 Returns: vital_signs: 生命体征 """ if len(clusters) == 0: return {"breathing_rate": 0, "heart_rate": 0} target = clusters[0] phase_signal = target["phase_history"] unwrapped = np.unwrap(phase_signal) breathing_signal = self.bandpass_filter(unwrapped, 0.1, 0.5, fs=10) heart_signal = self.bandpass_filter(unwrapped, 0.8, 2.0, fs=10) breathing_rate = self.estimate_frequency(breathing_signal, fs=10) heart_rate = self.estimate_frequency(heart_signal, fs=10) return { "breathing_rate": breathing_rate, "heart_rate": heart_rate } def bandpass_filter(self, signal, low, high, fs): """ 带通滤波 Args: signal: 输入信号 low: 低频截止 high: 高频截止 fs: 采样频率 Returns: filtered: 滤波后信号 """ nyq = fs / 2 low_norm = low / nyq high_norm = high / nyq b, a = butter(2, [low_norm, high_norm], btype='band') filtered = filtfilt(b, a, signal) return filtered def estimate_frequency(self, signal, fs): """ 估计信号主频率 Args: signal: 输入信号 fs: 采样频率 Returns: frequency: 主频率 (Hz) """ fft = np.fft.fft(signal) freqs = np.fft.fftfreq(len(signal), 1/fs) magnitude = np.abs(fft) peaks, _ = find_peaks(magnitude[:len(magnitude)//2]) if len(peaks) == 0: return 0 peak_idx = peaks[np.argmax(magnitude[peaks])] freq = freqs[peak_idx] return abs(freq) * 60 def classify(self, clusters, vital_signs): """ 分类:成人/儿童/空座 Args: clusters: 目标簇 vital_signs: 生命体征 Returns: classification: 分类结果 """ if len(clusters) == 0: return {"type": "empty", "confidence": 0.99} breathing = vital_signs["breathing_rate"] heart = vital_signs["heart_rate"] if breathing > 30: return {"type": "child", "confidence": 0.85} else: return {"type": "adult", "confidence": 0.80}
if __name__ == "__main__": detector = CPDDetector({}) adc_data = np.random.randn(64, 256) result = detector.process_frame(adc_data) print(f"占用: {result['occupancy']}") print(f"呼吸: {result['vital_signs']['breathing_rate']:.1f} 次/分钟") print(f"心跳: {result['vital_signs']['heart_rate']:.1f} 次/分钟") print(f"分类: {result['classification']['type']}")
|