forth commit

This commit is contained in:
ZhangJinLong 2025-08-14 11:16:24 +08:00
parent e161dd7319
commit 08e3f2cede
17 changed files with 1300050 additions and 109 deletions

View File

@ -0,0 +1,82 @@
# 通道级滤波重构说明
## 问题描述
原来的滤波逻辑存在严重问题:
- **错误做法**:对单个数据包内的短时间序列进行滤波
- **问题**:滤波器无法获得足够的上下文信息,导致滤波效果差
- **后果**:信号质量下降,可能引入伪影
## 解决方案
新的通道级滤波逻辑:
1. **收集数据**:收集所有数据包中相同通道的完整数据
2. **整体滤波**:对完整通道数据进行滤波处理
3. **重新分配**:将滤波后的数据重新分配回数据包结构
## 核心方法
### `process_channel_based_filtering()`
- 输入:多个数据包的向量
- 输出:处理后的数据包向量
- 功能:实现通道级滤波的核心逻辑
### `apply_channel_filters()`
- 根据设备类型选择合适的滤波策略
- 支持EEG、ECG、PPG、呼吸、打鼾、听诊器等设备
## 使用方法
### 原来的错误用法
```cpp
// ❌ 错误:对单个数据包滤波
std::vector<SensorData> raw_packets = get_raw_data_packets();
for (auto& packet : raw_packets) {
packet = signal_processor.preprocess_signals(packet); // 错误!
}
```
### 新的正确用法
```cpp
// ✅ 正确:通道级滤波
std::vector<SensorData> raw_packets = get_raw_data_packets();
std::vector<SensorData> processed_packets =
signal_processor.process_channel_based_filtering(raw_packets);
```
## 滤波流程
```
原始数据包 → 按通道收集 → 完整通道滤波 → 重新分配 → 处理后数据包
↓ ↓ ↓ ↓ ↓
[包1,包2,包3] → [通道1数据] → [滤波后] → [新包1,新包2,新包3]
[通道2数据] → [滤波后]
[通道3数据] → [滤波后]
```
## 优势
1. **滤波质量提升**:滤波器获得完整的时间序列信息
2. **边界效应减少**:避免数据包边界处的滤波伪影
3. **计算效率**:批量处理,减少重复计算
4. **信号连续性**:保持通道数据的连续性
## 注意事项
1. **内存使用**:需要临时存储完整通道数据
2. **数据包重构**:滤波后需要重新构建数据包结构
3. **时序保持**:确保数据包的时间顺序正确
## 测试
运行测试文件验证功能:
```bash
g++ -o test_channel_filtering test_channel_filtering.cpp src/signal_processor/signal_processor.cpp -I./include
./test_channel_filtering
```
## 兼容性
- 保持原有API不变
- 新增方法不影响现有代码
- 可以逐步迁移到新的滤波逻辑

138489
channel_data_mapped_.csv Normal file

File diff suppressed because it is too large Load Diff

138489
channel_data_processed_.csv Normal file

File diff suppressed because it is too large Load Diff

47029
channel_data_transered_.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
class FileManager { class FileManager {
public: public:
static std::vector<uint8_t> readBinaryFile(const std::string& filename); // 读取二进制文件 static std::vector<uint8_t> readBinaryFile(const std::string& filename); // 读取二进制文件
bool is_mit_bih_file(const std::vector<uint8_t>& data);
}; };
void save_to_csv(const std::vector<SensorData>& all_data, const std::string& filename);//将数据写入csv void save_to_csv(const std::vector<SensorData>& all_data, const std::string& filename);//将数据写入csv
#endif #endif

View File

@ -20,6 +20,7 @@ SensorData parse_stethoscope(const uint8_t* data);
SensorData parse_snore(const uint8_t* data); SensorData parse_snore(const uint8_t* data);
SensorData parse_respiration(const uint8_t* data); SensorData parse_respiration(const uint8_t* data);
std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data); std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data);
SensorData parse_mit_bih(const uint8_t* data, size_t size, int num_channels, int samples_per_channel);
#endif #endif

View File

@ -1,5 +1,6 @@
#ifndef _HEADFILE_H #ifndef _HEADFILE_H
#define _HEADFILE_H #define _HEADFILE_H
#include "test.h" #include "test.h"
#include "data_receiver.h" #include "data_receiver.h"
#include <iostream> #include <iostream>
@ -24,7 +25,9 @@
#include <iterator> #include <iterator>
#include "File_manage.h" #include "File_manage.h"
#include <cmath> #include <cmath>
#include "indicator_cal.h"
#include <algorithm> #include <algorithm>
#include "feature_extractor.h" #include "feature_extractor.h"
#include <utility> // for std::pair #include <utility> // for std::pair
#endif #endif

18
include/indicator_cal.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _INDICATOR_CAL_H
#define _INDICATOR_CAL_H
#include "headfile.h"
class MetricsCalculator
{
public:
float calculate_heart_rate_ecg(const SensorData& ecg_signal, float sample_rate);
float calculate_t_wave_amplitude(const std::vector<float>& ecg_signal);
float calculate_heart_rate_ppg(const std::vector<float>& ppg_signal, float sample_rate);
float calculate_spo2(const SensorData& ppg_data);
float calculate_pulse_width(const std::vector<float>& ppg_signal);
float calculate_amplitude_ratio(const SensorData& ppg_data);
float calculate_sdnn(const std::vector<float>& rr_intervals);
float calculate_rmssd(const std::vector<float>& rr_intervals) ;
std::vector<float> detect_r_peaks(const std::vector<float>& ecg_signal, float sample_rate) ;
std::vector<float> detect_pulse_peaks(const std::vector<float>& ppg_signal, float sample_rate);
};
#endif

View File

@ -64,6 +64,11 @@ public:
// 预处理信号 // 预处理信号
SensorData preprocess_signals(const SensorData& raw_data); // 使用DataType枚举 SensorData preprocess_signals(const SensorData& raw_data); // 使用DataType枚举
SensorData preprocess_generic(const SensorData& data); SensorData preprocess_generic(const SensorData& data);
// 新增:通道级滤波处理
std::vector<SensorData> process_channel_based_filtering(
const std::vector<SensorData>& data_packets);
// 特征提取 // 特征提取
FeatureSet extract_signal_features(const SensorData& processed_data, FeatureSet extract_signal_features(const SensorData& processed_data,
const std::vector<std::string>& features = {}); const std::vector<std::string>& features = {});
@ -150,6 +155,23 @@ public:
float calculate_PPG_sqi(const std::vector<float>& red_channel, float calculate_PPG_sqi(const std::vector<float>& red_channel,
const std::vector<float>& ir_channel); const std::vector<float>& ir_channel);
float calculate_ecg_sqi(const std::vector<float>& signal, double sample_rate); float calculate_ecg_sqi(const std::vector<float>& signal, double sample_rate);
// 新增:通道级滤波辅助方法
private:
std::vector<std::vector<float>> apply_channel_filters(
const std::vector<std::vector<float>>& channels, DataType data_type);
std::vector<std::vector<float>> apply_eeg_filters(
const std::vector<std::vector<float>>& channels);
std::vector<std::vector<float>> apply_ecg_filters(
const std::vector<std::vector<float>>& channels);
std::vector<std::vector<float>> apply_ppg_filters(
const std::vector<std::vector<float>>& channels);
std::vector<std::vector<float>> apply_respiration_filters(
const std::vector<std::vector<float>>& channels);
std::vector<std::vector<float>> apply_snore_filters(
const std::vector<std::vector<float>>& channels);
std::vector<std::vector<float>> apply_stethoscope_filters(
const std::vector<std::vector<float>>& channels);
}; };

View File

@ -12,7 +12,8 @@ enum class DataType {
PPG, // 血氧 PPG, // 血氧
RESPIRATION, // 呼吸/姿态 RESPIRATION, // 呼吸/姿态
SNORE, // 鼾声 SNORE, // 鼾声
STETHOSCOPE // 数字听诊 STETHOSCOPE, // 数字听诊
MIT_BIH // 添加MIT-BIH心律失常数据集类型
}; };
// 导联脱落状态 // 导联脱落状态

View File

@ -1,4 +1,5 @@
#include "headfile.h" #include "headfile.h"
std::vector<float> heart_rate;
// 辅助函数:打印多通道数据 // 辅助函数:打印多通道数据
void print_multi_channel(const std::vector<std::vector<float>>& channels) { void print_multi_channel(const std::vector<std::vector<float>>& channels) {
for (size_t ch = 0; ch < channels.size(); ++ch) { for (size_t ch = 0; ch < channels.size(); ++ch) {
@ -19,32 +20,51 @@ void print_channel_data(const std::variant<std::vector<float>, std::vector<std::
print_multi_channel(multi_channel); print_multi_channel(multi_channel);
} }
} }
void test_mit_bih() {
try {
// 读取MIT-BIH数据文件
std::vector<uint8_t> file_content = FileManager::readBinaryFile("C:/Users/29096/Desktop/work/mit-bih-arrhythmia-database-1.0.0/222.dat");
// 解析数据
std::vector<SensorData> all_data = parse_device_data(file_content);
// 保存结果
save_to_csv(all_data, "mit_bih_output.csv");
std::cout << "MIT-BIH数据处理完成" << std::endl;
std::cout << "Press Enter to exit..." << std::endl;
std::cin.get();
} catch (const std::exception& e) {
std::cerr << "处理错误: " << e.what() << std::endl;
}
}
void test_try() { void test_try() {
try { try {
// 1. 读取原始二进制文件 // 1. 读取原始二进制文件
std::vector<uint8_t> file_content = FileManager::readBinaryFile("C:/Users/29096/Documents/WeChat Files/wxid_sh93l5lycr8b22/FileStorage/File/2025-07/ecg_data_raw.dat"); std::vector<uint8_t> file_content = FileManager::readBinaryFile("C:/Users/29096/Documents/WeChat Files/wxid_sh93l5lycr8b22/FileStorage/File/2025-07/ecg_data_raw.dat");
Mapper mapper; Mapper mapper;
SignalProcessor processor;
MetricsCalculator calculator;
// 2. 解析设备数据包 - 需要实现此函数 // 2. 解析设备数据包 - 需要实现此函数
std::vector<SensorData> all_data = parse_device_data(file_content); std::vector<SensorData> all_data = parse_device_data(file_content);
save_to_csv(all_data, "channel_data_transered_.csv"); std::cout<<"1"<<std::endl;
// 3. 创建信号处理器实例 for(auto& mapped_data:all_data)
/* SignalProcessor processor; {
// 4. 遍历所有数据包 mapped_data = mapper.DataMapper(mapped_data);//通道映射
for (auto& data : all_data) { }
// 打印原始数据信息 save_to_csv(all_data, "channel_data_mapped_.csv");
// print_parsed_result(data); // 需要实现此函数 for(auto& processed_data:all_data)
std::cout << "Before mapping (ECG-12):" << std::endl; {
std::cout << "Packet SN: " << data.packet_sn << ", Data Type: " << static_cast<int>(data.data_type) << std::endl;*/ processed_data = processor.preprocess_signals(processed_data); //十二导联心电
// print_channel_data(data.channel_data); }
/* SensorData mapped_ecg_12lead = mapper.DataMapper(data); for(auto& calculated_data:all_data)
SensorData processed_ecg_12_lead = processor.preprocess_signals(mapped_ecg_12lead); {
std::cout << "After mapping (ECG-12):" << std::endl; heart_rate.push_back(calculator.calculate_heart_rate_ecg(calculated_data,250)); //十二导联心电
std::cout << "Packet SN: " << mapped_ecg_12lead.packet_sn << ", Data Type: " << static_cast<int>(mapped_ecg_12lead.data_type) << std::endl; }
print_channel_data(mapped_ecg_12lead.channel_data); for(uint16_t i;i<heart_rate.size();i++) std::cout<<heart_rate[i]<<std::endl;
std::cout << "After processed (ECG-12):" << std::endl; save_to_csv(all_data, "channel_data_processed_.csv");
std::cout << "Packet SN: " << mapped_ecg_12lead.packet_sn << ", Data Type: " << static_cast<int>(mapped_ecg_12lead.data_type) << std::endl;
print_channel_data(processed_ecg_12_lead.channel_data);
}*/
}catch (const std::exception& e) { }catch (const std::exception& e) {
std::cerr << "解析错误: " << e.what() << std::endl; std::cerr << "解析错误: " << e.what() << std::endl;
@ -57,7 +77,6 @@ void test_try() {
} }
int main() { int main() {
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
test_try(); test_try(); // 测试MIT-BIH数据处理
return 0; return 0;
} }

975001
mit_bih_output.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -84,3 +84,11 @@ void save_to_csv(const std::vector<SensorData>& all_data, const std::string& fil
outfile.close(); outfile.close();
std::cout << "数据已保存至: " << filename << std::endl; std::cout << "数据已保存至: " << filename << std::endl;
} }
// 检测是否为MIT-BIH文件
bool FileManager::is_mit_bih_file(const std::vector<uint8_t>& data) {
// 简单启发式检测检查文件大小是否匹配典型MIT-BIH格式
// 实际应用中应该解析头文件(.hea)获取确切信息
const size_t size = data.size();
std::cout<<size<<std::endl;
return (size > 1024 && size % (2 * sizeof(int16_t)) == 0);
}

View File

@ -0,0 +1,313 @@
// metrics_calculator.cpp
#include "indicator_cal.h"
#include <cmath>
#include <algorithm>
#include <numeric>
// 辅助函数从SensorData获取单通道数据
static const std::vector<float>& get_single_channel(const SensorData& data) {
if (std::holds_alternative<std::vector<float>>(data.channel_data)) {
return std::get<std::vector<float>>(data.channel_data);
} else {
const auto& channels = std::get<std::vector<std::vector<float>>>(data.channel_data);
if (!channels.empty()) {
return channels[0]; // 返回第一通道
}
static const std::vector<float> empty;
return empty;
}
}
// ECG心率计算
float MetricsCalculator::calculate_heart_rate_ecg(const SensorData& ecg_signal, float sample_rate) {
const auto& signal = get_single_channel(ecg_signal);
if (signal.size() < 3 || sample_rate <= 0) return 0.0f;
// 检测R峰
auto r_peaks = detect_r_peaks(signal, sample_rate);
if (r_peaks.size() < 2) return 0.0f; // 至少需要2个R峰计算心率
// 计算平均RR间期
float total_rr = 0.0f;
for (size_t i = 1; i < r_peaks.size(); i++) {
total_rr += r_peaks[i] - r_peaks[i-1];
}
float avg_rr = total_rr / (r_peaks.size() - 1);
// 转换为心率 (次/分钟)
return 60.0f / (avg_rr / sample_rate);
}
// T波振幅计算
float MetricsCalculator::calculate_t_wave_amplitude(const std::vector<float>& ecg_signal) {
if (ecg_signal.empty()) return 0.0f;
// 计算QRS波群后的平均振幅代表T波
const size_t window_start = static_cast<size_t>(ecg_signal.size() * 0.3); // QRS后约30%位置
const size_t window_end = static_cast<size_t>(ecg_signal.size() * 0.5); // 50%位置
float max_amplitude = 0.0f;
for (size_t i = window_start; i < window_end && i < ecg_signal.size(); i++) {
if (std::abs(ecg_signal[i]) > max_amplitude) {
max_amplitude = std::abs(ecg_signal[i]);
}
}
return max_amplitude;
}
// PPG心率计算
float MetricsCalculator::calculate_heart_rate_ppg(const std::vector<float>& ppg_signal, float sample_rate) {
if (ppg_signal.size() < 3 || sample_rate <= 0) return 0.0f;
// 检测脉搏波峰
auto pulse_peaks = detect_pulse_peaks(ppg_signal, sample_rate);
if (pulse_peaks.size() < 2) return 0.0f;
// 计算平均脉搏间期
float total_intervals = 0.0f;
for (size_t i = 1; i < pulse_peaks.size(); i++) {
total_intervals += pulse_peaks[i] - pulse_peaks[i-1];
}
float avg_interval = total_intervals / (pulse_peaks.size() - 1);
// 转换为心率 (次/分钟)
return 60.0f / (avg_interval / sample_rate);
}
// 血氧饱和度计算
float MetricsCalculator::calculate_spo2(const SensorData& ppg_data) {
if (!std::holds_alternative<std::vector<std::vector<float>>>(ppg_data.channel_data) ||
std::get<std::vector<std::vector<float>>>(ppg_data.channel_data).size() < 2) {
return 0.0f;
}
const auto& channels = std::get<std::vector<std::vector<float>>>(ppg_data.channel_data);
const auto& red_channel = channels[0];
const auto& ir_channel = channels[1];
// 计算红光和红外光的AC/DC分量
auto calc_ac_dc = [](const std::vector<float>& signal) -> std::pair<float, float> {
float max_val = *std::max_element(signal.begin(), signal.end());
float min_val = *std::min_element(signal.begin(), signal.end());
float dc = (max_val + min_val) / 2.0f;
float ac = (max_val - min_val) / 2.0f;
return {ac, dc};
};
auto [red_ac, red_dc] = calc_ac_dc(red_channel);
auto [ir_ac, ir_dc] = calc_ac_dc(ir_channel);
// 计算R值 (红光AC/DC与红外光AC/DC的比值)
float r_value = (red_ac / red_dc) / (ir_ac / ir_dc);
// 经验公式计算SpO2 (需要根据设备校准)
return 110.0f - 25.0f * r_value;
}
// 脉搏波宽度计算
float MetricsCalculator::calculate_pulse_width(const std::vector<float>& ppg_signal) {
if (ppg_signal.empty()) return 0.0f;
// 找到最大峰值位置
auto max_it = std::max_element(ppg_signal.begin(), ppg_signal.end());
size_t peak_idx = std::distance(ppg_signal.begin(), max_it);
// 找到上升沿起点 (信号值小于峰值的10%)
size_t start_idx = peak_idx;
while (start_idx > 0 && ppg_signal[start_idx] > 0.1f * *max_it) {
start_idx--;
}
// 找到下降沿终点 (信号值小于峰值的10%)
size_t end_idx = peak_idx;
while (end_idx < ppg_signal.size() - 1 && ppg_signal[end_idx] > 0.1f * *max_it) {
end_idx++;
}
return static_cast<float>(end_idx - start_idx);
}
// 红光/红外光振幅比
float MetricsCalculator::calculate_amplitude_ratio(const SensorData& ppg_data) {
if (!std::holds_alternative<std::vector<std::vector<float>>>(ppg_data.channel_data) ||
std::get<std::vector<std::vector<float>>>(ppg_data.channel_data).size() < 2) {
return 0.0f;
}
const auto& channels = std::get<std::vector<std::vector<float>>>(ppg_data.channel_data);
const auto& red_channel = channels[0];
const auto& ir_channel = channels[1];
float red_amp = *std::max_element(red_channel.begin(), red_channel.end()) -
*std::min_element(red_channel.begin(), red_channel.end());
float ir_amp = *std::max_element(ir_channel.begin(), ir_channel.end()) -
*std::min_element(ir_channel.begin(), ir_channel.end());
return (ir_amp > 0.0001f) ? red_amp / ir_amp : 0.0f;
}
// HRV指标 - SDNN (RR间期的标准差)
float MetricsCalculator::calculate_sdnn(const std::vector<float>& rr_intervals) {
if (rr_intervals.size() < 2) return 0.0f;
float mean = std::accumulate(rr_intervals.begin(), rr_intervals.end(), 0.0f) / rr_intervals.size();
float variance = 0.0f;
for (float rr : rr_intervals) {
variance += (rr - mean) * (rr - mean);
}
variance /= rr_intervals.size();
return std::sqrt(variance);
}
// HRV指标 - RMSSD (相邻RR间期差值的均方根)
float MetricsCalculator::calculate_rmssd(const std::vector<float>& rr_intervals) {
if (rr_intervals.size() < 2) return 0.0f;
float sum_sq_diff = 0.0f;
for (size_t i = 1; i < rr_intervals.size(); i++) {
float diff = rr_intervals[i] - rr_intervals[i-1];
sum_sq_diff += diff * diff;
}
return std::sqrt(sum_sq_diff / (rr_intervals.size() - 1));
}
// 改进的R峰检测算法 (基于Pan-Tompkins算法)
std::vector<float> MetricsCalculator::detect_r_peaks(const std::vector<float>& ecg_signal, float sample_rate) {
std::vector<float> r_peaks;
if (ecg_signal.size() < 5 || sample_rate <= 0) return r_peaks;
const size_t n = ecg_signal.size();
// 1. 计算积分窗口大小 (150ms窗口)
const int win_integ = static_cast<int>(0.15f * sample_rate + 0.5f); // 四舍五入
if (win_integ < 1) return r_peaks;
// 有效数据起始位置 (滤波+积分导致的延迟)
const size_t start_index = 5 + win_integ - 1;
// 2. 带通滤波 (通过移动平均近似)
std::vector<float> filtered(n, 0.0f);
// 低通滤波 (5点移动平均)
for (size_t i = 4; i < n; i++) {
filtered[i] = (ecg_signal[i-4] + ecg_signal[i-3] +
ecg_signal[i-2] + ecg_signal[i-1] +
ecg_signal[i]) / 5.0f;
}
// 3. 微分 (增强QRS斜率)
std::vector<float> diff(n, 0.0f);
for (size_t i = 5; i < n; i++) {
diff[i] = filtered[i] - filtered[i-1];
}
// 4. 平方 (放大高频分量)
std::vector<float> sqrd(n, 0.0f);
for (size_t i = 0; i < n; i++) {
sqrd[i] = diff[i] * diff[i];
}
// 5. 移动平均积分 (突出QRS复合波)
std::vector<float> integrated(n, 0.0f);
for (size_t i = start_index; i < n; i++) {
float sum = 0.0f;
for (int j = 0; j < win_integ; j++) {
sum += sqrd[i - j];
}
integrated[i] = sum / win_integ;
}
// 6. 自适应阈值检测
float threshold = 0.0f;
float peak_value = 0.0f;
const size_t min_interval = static_cast<size_t>(0.2f * sample_rate); // 200ms最小间隔
// 初始阈值设置 (使用前2秒数据)
const size_t init_win = std::min(static_cast<size_t>(2 * sample_rate), n - start_index);
if (init_win > 10) {
auto max_it = std::max_element(integrated.begin() + start_index,
integrated.begin() + start_index + init_win);
threshold = 0.5f * (*max_it);
} else {
threshold = 0.5f * (*std::max_element(integrated.begin(), integrated.end()));
}
// 噪声和信号峰值跟踪
float noise_peak = 0.25f * threshold;
float signal_peak = threshold;
const float decay_rate = 0.125f; // 阈值衰减率
size_t last_peak = 0;
bool found_peak = false;
for (size_t i = start_index + 1; i < n - 1; i++) {
// 检测峰值 (大于前后两点)
if (integrated[i] > integrated[i-1] &&
integrated[i] > integrated[i+1] &&
integrated[i] > threshold) {
// 检查最小间隔
if (last_peak == 0 || i - last_peak > min_interval) {
r_peaks.push_back(static_cast<float>(i));
last_peak = i;
found_peak = true;
peak_value = integrated[i];
}
}
// 自适应阈值更新
if (found_peak) {
// 检测到峰值后更新信号阈值
signal_peak = decay_rate * peak_value + (1 - decay_rate) * signal_peak;
found_peak = false;
} else {
// 未检测到峰值时更新噪声阈值
if (integrated[i] > noise_peak) {
noise_peak = decay_rate * integrated[i] + (1 - decay_rate) * noise_peak;
}
}
// 组合阈值 (信号和噪声阈值的加权平均)
threshold = 0.25f * signal_peak + 0.75f * noise_peak;
}
return r_peaks;
}
// 脉搏波峰检测
std::vector<float> MetricsCalculator::detect_pulse_peaks(const std::vector<float>& ppg_signal, float sample_rate) {
std::vector<float> pulse_peaks;
if (ppg_signal.empty()) return pulse_peaks;
// 自适应阈值
float threshold = 0.6f * (*std::max_element(ppg_signal.begin(), ppg_signal.end()));
// 最小脉搏间隔 (300ms ≈ 200bpm)
const size_t min_interval = static_cast<size_t>(0.3f * sample_rate);
bool in_peak = false;
size_t last_peak = 0;
for (size_t i = 1; i < ppg_signal.size() - 1; i++) {
// 检测上升沿
if (!in_peak && ppg_signal[i] > threshold &&
ppg_signal[i] > ppg_signal[i-1] && ppg_signal[i] > ppg_signal[i+1]) {
if (i - last_peak > min_interval || last_peak == 0) {
pulse_peaks.push_back(static_cast<float>(i));
last_peak = i;
in_peak = true;
}
}
// 检测下降沿
if (in_peak && ppg_signal[i] < 0.7f * threshold) {
in_peak = false;
}
}
return pulse_peaks;
}

View File

@ -104,7 +104,7 @@ SensorData Mapper::ECG_12LEAD_Data_Mapper(SensorData& data)
// 处理前8个通道 // 处理前8个通道
for (int ch = 0; ch < 8; ++ch) { for (int ch = 0; ch < 8; ++ch) {
for (int sample = 0; sample < 14; ++sample) { for (int sample = 0; sample < 14; ++sample) {
channels[ch][sample] = ecg_data[ch * 14 + sample] * 0.318f; channels[ch][sample] = ecg_data[ch * 14 + sample]*0.318;
} }
} }

View File

@ -220,6 +220,52 @@ SensorData parse_12lead_ecg(const uint8_t* data) {
return result; return result;
} }
// MIT-BIH 212格式解析器
SensorData parse_mit_bih_212(const uint8_t* data, size_t size) {
SensorData result;
result.data_type = DataType::MIT_BIH;
result.packet_sn = 0; // 单文件数据SN设为0
result.lead_status = {{0}}; // 无导联状态
result.timestamp = 0; // 无时间戳
// 检查文件大小是否合理
if (size < 1024 || size % 2 != 0) {
throw std::runtime_error("无效的MIT-BIH文件大小");
}
// 解析212格式数据
auto& channels = result.channel_data.emplace<std::vector<std::vector<float>>>();
channels.resize(2); // 两个导联
// 212格式: 每2字节包含两个12位样本
for (size_t i = 0; i < size; i += 2) {
uint8_t byte1 = data[i];
uint8_t byte2 = data[i+1];
// 解析第一个通道 (低12位)
int16_t sample1 = ((byte1 & 0x0F) << 8) | byte2;
// 符号扩展 (12位有符号 -> 16位有符号)
if (sample1 & 0x0800) sample1 |= 0xF000;
// 解析第二个通道 (高12位)
int16_t sample2 = ((byte1 & 0xF0) << 4) | (byte2 >> 4);
// 符号扩展 (12位有符号 -> 16位有符号)
if (sample2 & 0x0800) sample2 |= 0xF000;
// 转换为毫伏 (MIT-BIH ADC范围: ±5mV = ±2048)
float mv1 = sample1 * (5.0f / 2048.0f);
float mv2 = sample2 * (5.0f / 2048.0f);
channels[0].push_back(mv1);
channels[1].push_back(mv2);
}
// 存储原始数据
result.raw_data.assign(data, data + size);
return result;
}
// 数字听诊解析 (0x1102) // 数字听诊解析 (0x1102)
SensorData parse_stethoscope(const uint8_t* data) { SensorData parse_stethoscope(const uint8_t* data) {
SensorData result; SensorData result;
@ -309,6 +355,7 @@ SensorData parse_respiration(const uint8_t* data) {
// 统一解析入口函数 - 支持多个帧头和数据包组 // 统一解析入口函数 - 支持多个帧头和数据包组
std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data) { std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data) {
FileManager manager_;
const size_t PACKET_SIZE = 238; // 每个数据包固定大小 const size_t PACKET_SIZE = 238; // 每个数据包固定大小
const size_t RESPONSE_HEADER_SIZE = 10; // 响应帧头大小 (2功能码 + 2数据长度 + 4实际采集点数+crc校验) const size_t RESPONSE_HEADER_SIZE = 10; // 响应帧头大小 (2功能码 + 2数据长度 + 4实际采集点数+crc校验)
const uint16_t FUNCTION_CODE = 0x0010; // 获取数据功能码 const uint16_t FUNCTION_CODE = 0x0010; // 获取数据功能码
@ -316,9 +363,8 @@ std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data)
const size_t file_size = file_data.size(); const size_t file_size = file_data.size();
const uint8_t* ptr = file_data.data(); const uint8_t* ptr = file_data.data();
const uint8_t* end_ptr = ptr + file_size; const uint8_t* end_ptr = ptr + file_size;
std::map<DataType, std::vector<SensorData>> grouped_data;
std::vector<SensorData> results; std::vector<SensorData> results;
while (ptr < end_ptr) { while (ptr < end_ptr) {
// 检查是否有响应帧头 // 检查是否有响应帧头
bool has_response_header = false; bool has_response_header = false;
@ -440,6 +486,39 @@ std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data)
} }
} }
} }
// 将解析的结果按数据类型分组
for (const auto& result : results) {
grouped_data[result.data_type].push_back(result);
}
for (auto& [data_type, packets] : grouped_data) {
if (packets.empty()) continue;
// 创建新的SensorData对象包含完整通道数据
SensorData full_data = packets[0];
full_data.channel_data = std::vector<std::vector<float>>();
// 获取通道数量
size_t num_channels = 0;
if (auto* channels = std::get_if<std::vector<std::vector<float>>>(&packets[0].channel_data)) {
num_channels = channels->size();
full_data.channel_data.emplace<std::vector<std::vector<float>>>(num_channels);
}
// 合并所有数据包中的通道数据
auto& full_channels = std::get<std::vector<std::vector<float>>>(full_data.channel_data);
for (size_t ch = 0; ch < num_channels; ch++) {
for (auto& packet : packets) {
if (auto* channels = std::get_if<std::vector<std::vector<float>>>(&packet.channel_data)) {
if (ch < channels->size()) {
full_channels[ch].insert(full_channels[ch].end(),
(*channels)[ch].begin(),
(*channels)[ch].end());
}
}
}
}
results.push_back(full_data);
}
return results; return results;
} }

View File

@ -1,4 +1,264 @@
#include "signal_processor.h" #include "signal_processor.h"
// 新增:处理多个数据包的通道级滤波
std::vector<SensorData> SignalProcessor::process_channel_based_filtering(
const std::vector<SensorData>& data_packets) {
if (data_packets.empty()) return {};
// 按数据类型分组
std::map<DataType, std::vector<SensorData>> grouped_data;
for (const auto& packet : data_packets) {
grouped_data[packet.data_type].push_back(packet);
}
std::vector<SensorData> processed_packets;
// 对每种数据类型分别处理
for (auto& [data_type, packets] : grouped_data) {
if (packets.empty()) continue;
// 获取第一个数据包作为模板
SensorData template_packet = packets[0];
// 收集所有通道的完整数据
std::vector<std::vector<float>> all_channels;
size_t num_channels = 0;
// 确定通道数量
if (auto* channels = std::get_if<std::vector<std::vector<float>>>(&packets[0].channel_data)) {
num_channels = channels->size();
all_channels.resize(num_channels);
}
// 收集所有数据包中相同通道的数据
for (size_t ch = 0; ch < num_channels; ch++) {
for (const auto& packet : packets) {
if (auto* channels = std::get_if<std::vector<std::vector<float>>>(&packet.channel_data)) {
if (ch < channels->size()) {
all_channels[ch].insert(all_channels[ch].end(),
(*channels)[ch].begin(),
(*channels)[ch].end());
}
}
}
}
// 对完整通道数据进行滤波处理
std::vector<std::vector<float>> filtered_channels =
apply_channel_filters(all_channels, data_type);
// 将滤波后的数据重新分配回数据包结构
size_t samples_per_packet = 0;
if (auto* channels = std::get_if<std::vector<std::vector<float>>>(&packets[0].channel_data)) {
if (!channels->empty()) {
samples_per_packet = (*channels)[0].size();
}
}
// 重新构建数据包
size_t total_samples = filtered_channels[0].size();
size_t num_packets = (total_samples + samples_per_packet - 1) / samples_per_packet;
for (size_t p = 0; p < num_packets; p++) {
SensorData new_packet = template_packet;
new_packet.packet_sn = p; // 重新分配包序号
// 创建新的通道数据结构
auto& new_channels = new_packet.channel_data.emplace<std::vector<std::vector<float>>>();
new_channels.resize(num_channels);
// 分配数据到各个通道
for (size_t ch = 0; ch < num_channels; ch++) {
size_t start_idx = p * samples_per_packet;
size_t end_idx = std::min(start_idx + samples_per_packet, filtered_channels[ch].size());
if (start_idx < filtered_channels[ch].size()) {
new_channels[ch].assign(filtered_channels[ch].begin() + start_idx,
filtered_channels[ch].begin() + end_idx);
}
}
processed_packets.push_back(new_packet);
}
}
return processed_packets;
}
// 新增:对完整通道数据应用滤波器
std::vector<std::vector<float>> SignalProcessor::apply_channel_filters(
const std::vector<std::vector<float>>& channels, DataType data_type) {
std::vector<std::vector<float>> filtered_channels = channels;
switch (data_type) {
case DataType::EEG:
filtered_channels = apply_eeg_filters(channels);
break;
case DataType::ECG_2LEAD:
case DataType::ECG_12LEAD:
filtered_channels = apply_ecg_filters(channels);
break;
case DataType::PPG:
filtered_channels = apply_ppg_filters(channels);
break;
case DataType::RESPIRATION:
filtered_channels = apply_respiration_filters(channels);
break;
case DataType::SNORE:
filtered_channels = apply_snore_filters(channels);
break;
case DataType::STETHOSCOPE:
filtered_channels = apply_stethoscope_filters(channels);
break;
default:
// 通用滤波
for (auto& channel : filtered_channels) {
channel = bandpass_filter(channel, 250.0, 0.5, 45.0);
}
break;
}
return filtered_channels;
}
// 新增EEG通道滤波
std::vector<std::vector<float>> SignalProcessor::apply_eeg_filters(
const std::vector<std::vector<float>>& channels) {
const double SAMPLE_RATE = 250.0;
std::vector<std::vector<float>> filtered_channels = channels;
if (channels.size() < 8) return filtered_channels;
// 分离EEG和EOG通道
std::vector<std::vector<float>> eeg_channels(channels.begin(), channels.begin() + 6);
std::vector<std::vector<float>> eog_channels(channels.begin() + 6, channels.end());
// 处理EEG通道
for (auto& channel : eeg_channels) {
// 眼电伪迹补偿
if (eog_channels.size() >= 2) {
channel = compensate_eog_artifact(channel, eog_channels[0], eog_channels[1]);
}
// 50Hz自适应陷波滤波
channel = adaptive_notch_filter(channel, SAMPLE_RATE, 50.0, 5.0);
// 0.5-45Hz带通滤波
channel = bandpass_filter(channel, SAMPLE_RATE, 0.5, 45.0);
}
// 处理EOG通道
for (auto& channel : eog_channels) {
channel = bandpass_filter(channel, SAMPLE_RATE, 0.5, 30.0);
}
// 合并处理后的通道
filtered_channels.clear();
filtered_channels.insert(filtered_channels.end(), eeg_channels.begin(), eeg_channels.end());
filtered_channels.insert(filtered_channels.end(), eog_channels.begin(), eog_channels.end());
return filtered_channels;
}
// 新增ECG通道滤波
std::vector<std::vector<float>> SignalProcessor::apply_ecg_filters(
const std::vector<std::vector<float>>& channels) {
const double SAMPLE_RATE = 250.0;
std::vector<std::vector<float>> filtered_channels = channels;
for (auto& channel : filtered_channels) {
// 0.5Hz高通滤波
channel = Highpass_filter(channel, SAMPLE_RATE, 0.5);
// 50Hz自适应陷波滤波
channel = adaptive_notch_filter(channel, SAMPLE_RATE, 50.0, 5.0);
// 25-40Hz带阻滤波
channel = bandstop_filter(channel, SAMPLE_RATE, 25.0, 40.0);
}
return filtered_channels;
}
// 新增PPG通道滤波
std::vector<std::vector<float>> SignalProcessor::apply_ppg_filters(
const std::vector<std::vector<float>>& channels) {
const double SAMPLE_RATE = 50.0;
std::vector<std::vector<float>> filtered_channels = channels;
for (auto& channel : filtered_channels) {
// 移除直流分量
channel = remove_dc_offset(channel);
// 0.5-10Hz带通滤波
channel = bandpass_filter(channel, SAMPLE_RATE, 0.5, 10.0);
}
return filtered_channels;
}
// 新增:呼吸通道滤波
std::vector<std::vector<float>> SignalProcessor::apply_respiration_filters(
const std::vector<std::vector<float>>& channels) {
const double SAMPLE_RATE = 100.0;
std::vector<std::vector<float>> filtered_channels = channels;
for (auto& channel : filtered_channels) {
// 0.1Hz高通滤波
channel = filter(channel, SAMPLE_RATE, 0, 0.1, filtertype::highpass);
// 50Hz陷波滤波
channel = adaptive_notch_filter(channel, SAMPLE_RATE, 50.0, 5.0);
// 振幅归一化
normalize_amplitude(channel);
}
return filtered_channels;
}
// 新增:打鼾通道滤波
std::vector<std::vector<float>> SignalProcessor::apply_snore_filters(
const std::vector<std::vector<float>>& channels) {
const double SAMPLE_RATE = 2000.0;
std::vector<std::vector<float>> filtered_channels = channels;
for (auto& channel : filtered_channels) {
// 50-2000Hz带通滤波
channel = bandpass_filter(channel, SAMPLE_RATE, 50.0, 2000.0);
// 振幅归一化
normalize_amplitude(channel);
}
return filtered_channels;
}
// 新增:听诊器通道滤波
std::vector<std::vector<float>> SignalProcessor::apply_stethoscope_filters(
const std::vector<std::vector<float>>& channels) {
const double SAMPLE_RATE = 4000.0;
std::vector<std::vector<float>> filtered_channels = channels;
for (auto& channel : filtered_channels) {
// 20-2000Hz带通滤波
channel = bandpass_filter(channel, SAMPLE_RATE, 20.0, 2000.0);
// 振幅归一化
normalize_amplitude(channel);
}
return filtered_channels;
}
SensorData SignalProcessor::preprocess_generic(const SensorData& data) { SensorData SignalProcessor::preprocess_generic(const SensorData& data) {
SensorData processed = data; SensorData processed = data;
@ -142,16 +402,18 @@ SensorData SignalProcessor::preprocess_ecg_12lead(const SensorData& data) {
throw std::runtime_error("Invalid channel count for 12-lead ECG"); throw std::runtime_error("Invalid channel count for 12-lead ECG");
} }
// 对每个导联独立进行信号处理 // 对每个导联独立进行信号处理
for (auto& channel : channels) { for (auto& channel : channels) {
// 1. 0.5Hz高通滤波 (去除基线漂移) // 1. 0.5Hz高通滤波 (去除基线漂移)
channel = filter(channel, SAMPLE_RATE, 0.5, 0.0, filtertype::highpass); //channel = remove_dc_offset(channel);
channel = filter(channel, SAMPLE_RATE,0,0.5, filtertype::highpass);
// 2. 50Hz自适应陷波滤波 (去除工频干扰) // 2. 50Hz自适应陷波滤波 (去除工频干扰)
channel = filter(channel, SAMPLE_RATE, 50.0, 60,filtertype::notchpass); channel = filter(channel, SAMPLE_RATE, 49.5, 51.5, filtertype::notchpass);
// 3. 25-40Hz带阻滤波 (去除肌电干扰) // 3. 25-40Hz带阻滤波 (去除肌电干扰)
channel = filter(channel, SAMPLE_RATE, 25.0, 40.0, filtertype::bandstop); channel = filter(channel, SAMPLE_RATE, 0.5, 0.6, filtertype::bandstop);
} }
// 计算并存储信号质量指数 // 计算并存储信号质量指数
@ -291,8 +553,7 @@ std::vector<float> SignalProcessor::remove_dc_offset(const std::vector<float>& s
float dc_remove = 0; float dc_remove = 0;
for(auto& val:signal) dc_remove += val; for(auto& val:signal) dc_remove += val;
dc_remove /= result.size(); dc_remove /= result.size();
for(auto& value:result) value -= dc_remove; for(auto& value:result) value -= dc_remove; return result;
return result;
} }
std::vector<float> SignalProcessor::apply_gain(const std::vector<float>& signal, float gain) { std::vector<float> SignalProcessor::apply_gain(const std::vector<float>& signal, float gain) {
std::vector<float> result = signal; std::vector<float> result = signal;
@ -310,45 +571,53 @@ std::vector<float> SignalProcessor::adaptive_notch_filter(const std::vector<floa
double sample_rate, double sample_rate,
double target_freq, double target_freq,
double bandwidth) { double bandwidth) {
std::vector<float> output(input.size(), 0.0f); if (input.empty()) return {};
// 计算滤波器系数 // 使用更稳定的实现
double omega0 = 2 * M_PI * target_freq / sample_rate; const double omega0 = 2 * M_PI * target_freq / sample_rate;
double alpha = sin(omega0) * sinh(log(2) / 2 * bandwidth * omega0 / sin(omega0)); const double alpha = sin(omega0) * sinh(log(2) / 2 * bandwidth * omega0 / sin(omega0));
double b0 = 1; // 系数计算
double b1 = -2 * cos(omega0); const double b0 = 1.0;
double b2 = 1; const double b1 = -2 * cos(omega0);
double a0 = 1 + alpha; const double b2 = 1.0;
double a1 = -2 * cos(omega0); const double a0 = 1 + alpha;
double a2 = 1 - alpha; const double a1 = -2 * cos(omega0);
const double a2 = 1 - alpha;
// 归一化系数 // 归一化系数
b0 /= a0; const double inv_a0 = 1.0 / a0;
b1 /= a0; const double nb0 = b0 * inv_a0;
b2 /= a0; const double nb1 = b1 * inv_a0;
a1 /= a0; const double nb2 = b2 * inv_a0;
a2 /= a0; const double na1 = a1 * inv_a0;
const double na2 = a2 * inv_a0;
// 初始化滤波器状态
double x1 = 0, x2 = 0;
double y1 = 0, y2 = 0;
// 应用滤波器 // 应用滤波器
std::vector<float> output(input.size());
double x1 = 0.0, x2 = 0.0;
double y1 = 0.0, y2 = 0.0;
for (size_t n = 0; n < input.size(); ++n) { for (size_t n = 0; n < input.size(); ++n) {
double x0 = input[n]; double x0 = input[n];
output[n] = b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2; double y = nb0 * x0 + nb1 * x1 + nb2 * x2 - na1 * y1 - na2 * y2;
// 防止不稳定
if (!std::isfinite(y)) y = 0.0;
output[n] = static_cast<float>(y);
// 更新状态 // 更新状态
x2 = x1; x2 = x1;
x1 = x0; x1 = x0;
y2 = y1; y2 = y1;
y1 = output[n]; y1 = y;
} }
return output; return output;
} }
std::vector<float> SignalProcessor::filter(const std::vector<float>& input, std::vector<float> SignalProcessor::filter(const std::vector<float>& input,
double sample_rate, double sample_rate,
double low_cutoff, double low_cutoff,
@ -375,34 +644,106 @@ std::vector<float> SignalProcessor::filter(const std::vector<float>& input,
std::vector<float> SignalProcessor::Lowpass_filter(const std::vector<float>& input, std::vector<float> SignalProcessor::Lowpass_filter(const std::vector<float>& input,
double sample_rate, double sample_rate,
double low_cutoff){ double low_cutoff){
if (input.empty()) return input; if (input.empty() || low_cutoff <= 0 || low_cutoff >= sample_rate/2) {
std::vector<float> output(input.size()); return input;
double A,f;
f = 1/sample_rate;
A = 1.0f/(1+(1/(2*M_PI*f*low_cutoff)));
output[0] = input[0];
if (input.size() > 1) output[1] = input[1];
for (size_t n = 2; n < input.size(); n++)
{
output[n] = A*input[n] + (1-A)*output[n-1];
} }
const double nyquist = sample_rate / 2.0;
const double omega = 2.0 * M_PI * low_cutoff / sample_rate;
const double k = 1.0 / tan(omega / 2.0); // 双线性变换预矫正
const double k2 = k * k;
const double sqrt2 = std::sqrt(2.0);
// 计算归一化系数
const double a0 = k2 + sqrt2 * k + 1;
const double b0 = 1.0 / a0;
const double b1 = 2 * b0;
const double b2 = b0;
const double a1 = 2 * (1 - k2) * b0;
const double a2 = (k2 - sqrt2 * k + 1) * b0;
// 应用滤波器
std::vector<float> output(input.size());
double x1 = 0.0, x2 = 0.0; // 输入延迟
double y1 = 0.0, y2 = 0.0; // 输出延迟
for (size_t i = 0; i < input.size(); ++i) {
const double x0 = input[i];
const double y0 = b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
output[i] = static_cast<float>(y0);
// 更新延迟
x2 = x1;
x1 = x0;
y2 = y1;
y1 = y0;
}
return output; return output;
} }
//高通滤波器 //改进后的高通滤波实现
std::vector<float> SignalProcessor::Highpass_filter(const std::vector<float>& input, std::vector<float> SignalProcessor::Highpass_filter(const std::vector<float>& input,
double sample_rate, double sample_rate,
double high_cutoff){ double cutoff) {
if (input.empty()) return input; if (input.empty()) return input;
int a = input[0];
// 1. 计算滤波器系数(二阶巴特沃斯)
const double omega = 2.0 * M_PI * cutoff / sample_rate;
const double sn = sin(omega);
const double cs = cos(omega);
const double alpha = sn / (2.0 * 0.707); // Q=0.707 (Butterworth)
const double b0 = (1 + cs) / 2.0;
const double b1 = -(1 + cs);
const double b2 = b0;
const double a0 = 1 + alpha;
const double a1 = -2 * cs;
const double a2 = 1 - alpha;
// 2. 归一化系数
const double inv_a0 = 1.0 / a0;
const double nb0 = b0 * inv_a0;
const double nb1 = b1 * inv_a0;
const double nb2 = b2 * inv_a0;
const double na1 = a1 * inv_a0;
const double na2 = a2 * inv_a0;
// 3. 初始化状态(使用前两个样本值)
double x1 = input.size() > 0 ? input[0] : 0;
double x2 = x1;
double y1 = 0;
double y2 = 0;
// 4. 应用滤波器(处理边界条件)
std::vector<float> output(input.size()); std::vector<float> output(input.size());
double A,f; for (size_t n = 0; n < input.size(); ++n) {
f = 1/sample_rate; const double x0 = input[n];
A = 1.0f/(1+(1/(2*M_PI*f*high_cutoff)));
output[0] = input[0]; // 计算当前输出
if (input.size() > 1) output[1] = input[1]; double y = nb0 * x0 + nb1 * x1 + nb2 * x2 - na1 * y1 - na2 * y2;
for (size_t n = 2; n < input.size(); n++)
{ // 5. 稳定化处理防止NaN/Inf
output[n] = A*output[n-1] + A*(input[n]-input[n-1]); if (!std::isfinite(y)) y = 0.0;
output[n] = static_cast<float>(y);
// 6. 更新状态变量
x2 = x1;
x1 = x0;
y2 = y1;
y1 = y;
} }
// 7. 可选去除初始瞬态前100ms数据
/*const size_t transient_samples = static_cast<size_t>(0.1 * sample_rate);
if (output.size() > transient_samples) {
const float initial_value = output[transient_samples];
for (size_t i = 0; i < transient_samples; ++i) {
output[i] = initial_value;
}
}*/
return output; return output;
} }
// 带通滤波器 // 带通滤波器
@ -454,43 +795,68 @@ std::vector<float> SignalProcessor::bandpass_filter(const std::vector<float>& in
std::vector<float> SignalProcessor::bandstop_filter(const std::vector<float>& input, std::vector<float> SignalProcessor::bandstop_filter(const std::vector<float>& input,
double sample_rate, double sample_rate,
double low_cutoff, double low_cutoff,
double high_cutoff) { double high_cutoff)
{
if (input.empty()) return {}; if (input.empty()) return {};
if (low_cutoff >= high_cutoff) { if (low_cutoff >= high_cutoff) {
throw std::invalid_argument("Low cutoff must be less than high cutoff"); throw std::invalid_argument("Low cutoff must be less than high cutoff");
} }
if (input.size() < 4) return input; // 太短的信号无法有效滤波
std::vector<float> output(input.size(), 0.0f); const double f0 = (low_cutoff + high_cutoff) / 2.0;
const double f0 = (low_cutoff + high_cutoff) / 2.0; // 中心频率 const double bw = high_cutoff - low_cutoff;
const double BW = high_cutoff - low_cutoff; // 带宽
const double Q = f0 / BW; // 品质因数 // 1. 使用双线性变换进行频率预矫正
const double omega0 = 2 * M_PI * f0 / sample_rate; const double T = 1.0 / sample_rate;
const double alpha = sin(omega0) / (2 * Q); const double w0 = 2.0 * M_PI * f0;
const double wd = 2.0 * M_PI * bw;
// 预矫正模拟频率
const double wa = 2.0 / T * tan(w0 * T / 2.0);
const double Ba = 2.0 / T * tan(wd * T / 2.0);
// 2. 计算Butterworth滤波器系数
const double Q = wa / Ba; // 更精确的Q值计算
const double alpha = sin(w0 * T) / (2 * Q);
// 计算滤波器系数
const double b0 = 1.0; const double b0 = 1.0;
const double b1 = -2 * cos(omega0); const double b1 = -2.0 * cos(w0 * T);
const double b2 = 1.0; const double b2 = 1.0;
const double a0 = 1.0 + alpha; const double a0 = 1.0 + alpha;
const double a1 = -2 * cos(omega0); const double a1 = -2.0 * cos(w0 * T);
const double a2 = 1.0 - alpha; const double a2 = 1.0 - alpha;
// 归一化系数 // 3. 更精确的系数归一化
const double inv_a0 = 1.0 / a0; const double gain = 1.0 / a0; // 保证通带增益为1
const double nb0 = b0 * inv_a0; const double nb0 = b0 * gain;
const double nb1 = b1 * inv_a0; const double nb1 = b1 * gain;
const double nb2 = b2 * inv_a0; const double nb2 = b2 * gain;
const double na1 = a1 * inv_a0; const double na1 = a1 * gain;
const double na2 = a2 * inv_a0; const double na2 = a2 * gain;
// 滤波器状态 // 4. 应用滤波器(带合理状态初始化)
double x1 = 0.0, x2 = 0.0; std::vector<float> output(input.size());
double y1 = 0.0, y2 = 0.0; double x1 = input[0], x2 = input[0]; // 输入状态初始化
double y1 = 0.0, y2 = 0.0; // 输出状态初始化
// 使用前两个样本计算初始输出状态
if (input.size() >= 2) {
const double x0 = input[0];
y1 = nb0 * x0 + nb1 * x1 + nb2 * x2;
x2 = x1;
x1 = x0;
}
// 应用滤波器
for (size_t n = 0; n < input.size(); ++n) { for (size_t n = 0; n < input.size(); ++n) {
const double x0 = input[n]; const double x0 = input[n];
const double y = nb0 * x0 + nb1 * x1 + nb2 * x2 - na1 * y1 - na2 * y2; double y = nb0 * x0 + nb1 * x1 + nb2 * x2 - na1 * y1 - na2 * y2;
// 5. 添加输出限幅保护
const double input_max = *std::max_element(input.begin(), input.end());
const double safety_margin = 2.0 * input_max;
if (std::abs(y) > safety_margin) {
y = std::copysign(safety_margin, y);
}
output[n] = static_cast<float>(y); output[n] = static_cast<float>(y);
@ -500,17 +866,15 @@ std::vector<float> SignalProcessor::bandstop_filter(const std::vector<float>& in
y2 = y1; y2 = y1;
y1 = y; y1 = y;
} }
return output; return output;
} }
// 运动补偿 // 运动补偿
std::vector<float> SignalProcessor::compensate_motion_artifact(const std::vector<float>& ppg, std::vector<float> SignalProcessor::compensate_motion_artifact(const std::vector<float>& ppg,
const std::vector<float>& motion) { const std::vector<float>& motion) {
std::vector<float> output = ppg; std::vector<float> output = ppg;
return ppg; return ppg;
} }
// 辅助函数计算PPG信号质量指 // 辅助函数计算PPG信号质量指
float SignalProcessor::calculate_PPG_sqi(const std::vector<float>& red_channel, float SignalProcessor::calculate_PPG_sqi(const std::vector<float>& red_channel,
const std::vector<float>& ir_channel) { const std::vector<float>& ir_channel) {
return 0.0f; return 0.0f;
@ -622,3 +986,26 @@ void SignalProcessor::normalize_amplitude(std::vector<float>& signal) {
} }
} }
} }
// 使用示例:如何正确使用通道级滤波
/*
// 原来的错误用法(对单个数据包滤波):
std::vector<SensorData> raw_packets = get_raw_data_packets();
for (auto& packet : raw_packets) {
packet = signal_processor.preprocess_signals(packet); // 错误!对单个包滤波
}
// 新的正确用法(通道级滤波):
std::vector<SensorData> raw_packets = get_raw_data_packets();
std::vector<SensorData> processed_packets =
signal_processor.process_channel_based_filtering(raw_packets);
// 或者,如果你想保持原有的数据包结构,可以这样:
std::vector<SensorData> raw_packets = get_raw_data_packets();
std::vector<SensorData> processed_packets =
signal_processor.process_channel_based_filtering(raw_packets);
// 关键区别:
// 1. 原来:对每个数据包内的短时间序列进行滤波(错误)
// 2. 现在:收集所有数据包中相同通道的完整数据,进行滤波,然后重新分配
*/