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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
| """ 纺织传感器座舱生理监测系统
基于 Frontiers in Physiology 2026 论文 适配到汽车 IMS 座舱场景
传感器类型: 1. 纺织 ECG 电极(座椅靠背嵌入) 2. 胸廓运动带(安全带集成) 3. 信号处理单元(座椅下方)
对比传统方案: - 医疗 ECG: 12导联, AgCl电极, 凝胶 → 不可用于日常 - 纺织 ECG: 1导联, 织物电极, 干电极 → 座椅集成 """
import numpy as np from typing import Dict, Tuple from dataclasses import dataclass
@dataclass class TextileSensorConfig: """纺织传感器配置""" ecg_sample_rate: int = 250 ecg_bandwidth: Tuple[float, float] = (0.5, 40) resp_sample_rate: int = 50 resp_bandwidth: Tuple[float, float] = (0.1, 1.0) min_snr_db: float = 10.0 min_qrs_amplitude_uv: float = 50
class TextileECGProcessor: """ 纺织 ECG 信号处理器 处理汽车座舱环境噪声: - 发动机/路面振动 → 带通滤波 - 运动伪迹 → 自适应滤波 - 安全带压力变化 → 基线校正 """ def __init__(self, config: TextileSensorConfig): self.config = config self.sampling_rate = config.ecg_sample_rate def process(self, raw_ecg: np.ndarray) -> Dict: """ ECG 信号处理流水线 Args: raw_ecg: 原始 ECG 信号 (N,) Returns: dict with 'hr', 'hrv', 'quality', 'rr_intervals' """ from scipy.signal import butter, filtfilt b, a = butter(4, [0.5 / (self.sampling_rate/2), 40 / (self.sampling_rate/2)], btype='band') filtered = filtfilt(b, a, raw_ecg) baseline = np.convolve(filtered, np.ones(500)/500, mode='same') corrected = filtered - baseline threshold = np.std(corrected) * 2 r_peaks = self._detect_r_peaks(corrected, threshold) if len(r_peaks) > 2: rr_intervals = np.diff(r_peaks) / self.sampling_rate hr = 60 / np.mean(rr_intervals) hrv_rmssd = np.sqrt(np.mean(np.diff(rr_intervals)**2)) hrv_sdnn = np.std(rr_intervals) else: hr = 0 rr_intervals = np.array([]) hrv_rmssd = 0 hrv_sdnn = 0 snr = self._compute_snr(corrected, r_peaks) quality = 'good' if snr > self.config.min_snr_db else 'poor' return { 'hr': hr, 'hrv_rmssd': hrv_rmssd, 'hrv_sdnn': hrv_sdnn, 'quality': quality, 'snr_db': snr, 'rr_intervals': rr_intervals, 'r_peaks': r_peaks } def _detect_r_peaks(self, signal: np.ndarray, threshold: float) -> np.ndarray: """简化版 R 峰检测""" peaks = [] for i in range(1, len(signal)-1): if signal[i] > threshold and signal[i] > signal[i-1] and signal[i] > signal[i+1]: peaks.append(i) return np.array(peaks) def _compute_snr(self, signal: np.ndarray, peaks: np.ndarray) -> float: """计算信噪比""" if len(peaks) < 2: return 0.0 signal_power = np.mean(signal[peaks]**2) noise_mask = np.ones(len(signal), dtype=bool) for p in peaks: noise_mask[max(0,p-50):min(len(signal),p+50)] = False noise_power = np.mean(signal[noise_mask]**2) if noise_power == 0: return 100.0 return 10 * np.log10(signal_power / noise_power)
class RespiratoryProcessor: """呼吸信号处理器""" def __init__(self, sample_rate: int = 50): self.sample_rate = sample_rate def process(self, raw_resp: np.ndarray) -> Dict: """ 处理胸廓运动信号 Args: raw_resp: 原始呼吸信号 (N,) Returns: dict with 'frequency', 'amplitude', 'quality' """ from scipy.signal import butter, filtfilt b, a = butter(4, [0.1 / (self.sample_rate/2), 1.0 / (self.sample_rate/2)], btype='band') filtered = filtfilt(b, a, raw_resp) fft = np.fft.rfft(filtered) freqs = np.fft.rfftfreq(len(filtered), 1/self.sample_rate) power = np.abs(fft)**2 resp_freq_idx = np.argmax(power[1:]) + 1 resp_freq_hz = freqs[resp_freq_idx] resp_rate = resp_freq_hz * 60 amplitude = np.std(filtered) snr = power[resp_freq_idx] / (np.sum(power) - power[resp_freq_idx] + 1e-10) quality = 'good' if snr > 5 else 'poor' return { 'frequency': resp_rate, 'amplitude': amplitude, 'quality': quality, 'snr': snr }
if __name__ == "__main__": import time config = TextileSensorConfig() ecg_processor = TextileECGProcessor(config) resp_processor = RespiratoryProcessor(config.resp_sample_rate) t = np.arange(0, 30, 1/250) hr_true = 72 ecg_sim = 0.5 * np.sin(2 * np.pi * hr_true/60 * t) ecg_sim += 0.1 * np.random.randn(len(t)) t_resp = np.arange(0, 30, 1/50) resp_rate_true = 16 resp_sim = 0.8 * np.sin(2 * np.pi * resp_rate_true/60 * t_resp) resp_sim += 0.2 * np.random.randn(len(t_resp)) ecg_result = ecg_processor.process(ecg_sim) resp_result = resp_processor.process(resp_sim) print("=" * 60) print("纺织传感器座舱生理监测测试") print("=" * 60) print(f"\nECG 结果:") print(f" 心率: {ecg_result['hr']:.1f} bpm (真实: {hr_true})") print(f" HRV (RMSSD): {ecg_result['hrv_rmssd']:.3f} s") print(f" HRV (SDNN): {ecg_result['hrv_sdnn']:.3f} s") print(f" 信号质量: {ecg_result['quality']} (SNR: {ecg_result['snr_db']:.1f} dB)") print(f" R 峰数: {len(ecg_result['r_peaks'])}") print(f"\n呼吸结果:") print(f" 呼吸频率: {resp_result['frequency']:.1f} /min (真实: {resp_rate_true})") print(f" 呼吸幅度: {resp_result['amplitude']:.3f}") print(f" 信号质量: {resp_result['quality']} (SNR: {resp_result['snr']:.1f})") print("\n" + "=" * 60) print("IMS 座舱部署可行性:") print(f" ECG 信号可用率目标: 90%+ (论文: 93.4%)") print(f" 呼吸信号可用率目标: 75%+ (论文: 70.7-81.3%)") print(f" 心率检测误差: <5 bpm") print(f" 呼吸频率误差: <2 /min")
|