2025/8/26 commit

This commit is contained in:
ZhangJinLong 2025-08-26 15:07:17 +08:00
parent e520579c99
commit bd389eef55
6 changed files with 31 additions and 880 deletions

View File

@ -221,3 +221,4 @@ g++ -o test_motion_artifact test_motion_artifact.cpp
- 质量改善SNR提升8-15dB

View File

@ -2,7 +2,7 @@
#include <fstream>
#include <sstream>
#include <ctime>
#include <windows.h> // 引入 Windows API 头文件
std::vector<float> heart_rate;
@ -360,7 +360,7 @@ void process_ppg_a50_data() {
int main() {
SetConsoleOutputCP(CP_UTF8);
// 选择要运行的测试
std::cout << "请选择测试模式:" << std::endl;
std::cout << "1. 测试MIT-BIH数据处理" << std::endl;

View File

@ -1067,299 +1067,43 @@ float SignalProcessor::calculate_PPG_sqi(const std::vector<float>& red_channel,
std::vector<float> SignalProcessor::remove_motion_artifacts(const std::vector<float>& signal, double sample_rate) {
if (signal.empty()) return signal;
std::cout << "开始增强版运动伪迹检测和去除,信号长度: " << signal.size() << " 样本" << std::endl;
std::vector<float> result = signal;
const size_t min_window_size = static_cast<size_t>(0.1 * sample_rate); // 最小窗口0.1秒
const size_t max_window_size = static_cast<size_t>(2.0 * sample_rate); // 最大窗口2秒
const size_t window_size = static_cast<size_t>(0.5 * sample_rate); // 0.5秒窗口
if (signal.size() < min_window_size) {
std::cout << "信号长度不足,跳过运动伪迹检测" << std::endl;
return result;
if (signal.size() < window_size) return result;
// 使用滑动窗口检测运动伪迹
for (size_t i = window_size; i < signal.size(); ++i) {
// 计算窗口内的统计特性
float sum = 0.0f, sum_sq = 0.0f;
for (size_t j = i - window_size; j < i; ++j) {
sum += signal[j];
sum_sq += signal[j] * signal[j];
}
// 1. 多尺度运动伪迹检测
std::vector<bool> artifact_mask(signal.size(), false);
float mean = sum / window_size;
float variance = (sum_sq / window_size) - (mean * mean);
float std_dev = std::sqrt(std::max(0.0f, variance));
// 使用多个窗口大小进行检测
std::vector<size_t> window_sizes = {
static_cast<size_t>(0.1 * sample_rate), // 0.1秒 - 快速运动
static_cast<size_t>(0.5 * sample_rate), // 0.5秒 - 中等运动
static_cast<size_t>(1.0 * sample_rate), // 1.0秒 - 慢速运动
static_cast<size_t>(2.0 * sample_rate) // 2.0秒 - 长期漂移
};
std::cout << "使用多尺度检测窗口: ";
for (size_t ws : window_sizes) {
std::cout << ws << " ";
}
std::cout << "样本" << std::endl;
// 2. 统计特征检测
for (size_t ws : window_sizes) {
if (signal.size() < ws) continue;
for (size_t i = ws; i < signal.size(); ++i) {
// 计算滑动窗口统计特征
std::vector<float> window_data;
for (size_t j = i - ws; j < i; ++j) {
window_data.push_back(signal[j]);
}
// 计算统计特征
float mean = 0.0f, variance = 0.0f, skewness = 0.0f, kurtosis = 0.0f;
float sum = 0.0f, sum_sq = 0.0f, sum_cube = 0.0f, sum_quad = 0.0f;
for (float val : window_data) {
sum += val;
sum_sq += val * val;
sum_cube += val * val * val;
sum_quad += val * val * val * val;
}
mean = sum / ws;
variance = (sum_sq / ws) - (mean * mean);
if (variance > 1e-6f) {
float std_dev = std::sqrt(variance);
float normalized_std = std_dev / (std::abs(mean) + 1e-6f);
// 偏度和峰度计算
for (float val : window_data) {
float normalized_val = (val - mean) / std_dev;
skewness += normalized_val * normalized_val * normalized_val;
kurtosis += normalized_val * normalized_val * normalized_val * normalized_val;
}
skewness /= ws;
kurtosis /= ws;
// 运动伪迹检测条件
bool is_artifact = false;
// 条件1: 异常幅度变化
// 检测异常值(可能的运动伪迹)
float current_val = signal[i];
float z_score = std::abs(current_val - mean) / (std_dev + 1e-6f);
if (z_score > 4.0f) { // 提高阈值,减少误检
is_artifact = true;
// 如果Z-score > 3认为是运动伪迹
if (z_score > 3.0f) {
// 使用中值滤波替换异常值
std::vector<float> window_values;
for (size_t j = std::max(static_cast<size_t>(0), i - window_size/2);
j < std::min(signal.size(), i + window_size/2); ++j) {
window_values.push_back(signal[j]);
}
// 条件2: 异常统计特征
if (std::abs(skewness) > 2.0f || kurtosis > 8.0f) {
is_artifact = true;
}
// 条件3: 异常方差变化
if (normalized_std > 0.5f) {
is_artifact = true;
}
// 条件4: 梯度异常检测
if (i > 0) {
float gradient = std::abs(current_val - signal[i-1]);
float avg_gradient = 0.0f;
for (size_t j = 1; j < std::min(ws, i); ++j) {
avg_gradient += std::abs(signal[i-j] - signal[i-j-1]);
}
avg_gradient /= std::min(ws, i);
if (gradient > 3.0f * avg_gradient) {
is_artifact = true;
}
}
if (is_artifact) {
artifact_mask[i] = true;
if (!window_values.empty()) {
std::sort(window_values.begin(), window_values.end());
result[i] = window_values[window_values.size() / 2]; // 中值
}
}
}
}
// 3. 频域特征检测
std::cout << "开始频域特征检测..." << std::endl;
// 使用FFT检测异常频率成分
const size_t fft_size = std::min(static_cast<size_t>(1024), signal.size());
if (fft_size >= 64) {
std::vector<float> fft_window(fft_size);
std::vector<float> power_spectrum(fft_size / 2);
for (size_t i = 0; i < signal.size() - fft_size; i += fft_size / 4) { // 50%重叠
// 提取窗口数据
for (size_t j = 0; j < fft_size; ++j) {
fft_window[j] = signal[i + j];
}
// 应用窗函数Hanning窗
for (size_t j = 0; j < fft_size; ++j) {
float window_val = 0.5f * (1.0f - std::cos(2.0f * M_PI * j / (fft_size - 1)));
fft_window[j] *= window_val;
}
// 计算功率谱密度
for (size_t j = 0; j < fft_size / 2; ++j) {
power_spectrum[j] = 0.0f;
for (size_t k = 0; k < fft_size; ++k) {
float phase = 2.0f * M_PI * j * k / fft_size;
float real_part = fft_window[k] * std::cos(phase);
float imag_part = fft_window[k] * std::sin(phase);
power_spectrum[j] += real_part * real_part + imag_part * imag_part;
}
power_spectrum[j] /= fft_size;
}
// 检测异常频率成分
float total_power = 0.0f, high_freq_power = 0.0f;
for (size_t j = 0; j < fft_size / 2; ++j) {
total_power += power_spectrum[j];
if (j > fft_size / 4) { // 高频成分
high_freq_power += power_spectrum[j];
}
}
float high_freq_ratio = high_freq_power / (total_power + 1e-6f);
// 如果高频成分比例异常,标记为运动伪迹
if (high_freq_ratio > 0.3f) {
for (size_t j = i; j < std::min(i + fft_size, signal.size()); ++j) {
artifact_mask[j] = true;
}
}
}
}
// 4. 形态学检测
std::cout << "开始形态学检测..." << std::endl;
// 检测尖峰和突变
for (size_t i = 2; i < signal.size() - 2; ++i) {
float current = signal[i];
float prev = signal[i-1];
float next = signal[i+1];
float prev2 = signal[i-2];
float next2 = signal[i+2];
// 尖峰检测
if ((current > prev && current > next &&
current - prev > 2.0f * std::abs(next - prev)) ||
(current < prev && current < next &&
prev - current > 2.0f * std::abs(next - prev))) {
artifact_mask[i] = true;
}
// 突变检测
float local_std = std::sqrt((std::pow(prev2 - prev, 2) + std::pow(prev - current, 2) +
std::pow(current - next, 2) + std::pow(next - next2, 2)) / 4.0f);
if (std::abs(current - prev) > 3.0f * local_std) {
artifact_mask[i] = true;
}
}
// 5. 智能修复策略
std::cout << "开始智能修复..." << std::endl;
size_t artifact_count = 0;
for (size_t i = 0; i < signal.size(); ++i) {
if (artifact_mask[i]) {
artifact_count++;
// 根据伪迹类型选择修复策略
if (i > 0 && i < signal.size() - 1) {
// 策略1: 中值插值
std::vector<float> neighbors;
for (int offset = -2; offset <= 2; ++offset) {
int idx = static_cast<int>(i) + offset;
if (idx >= 0 && idx < static_cast<int>(signal.size()) && !artifact_mask[idx]) {
neighbors.push_back(signal[idx]);
}
}
if (!neighbors.empty()) {
if (neighbors.size() >= 3) {
// 使用中值
std::sort(neighbors.begin(), neighbors.end());
result[i] = neighbors[neighbors.size() / 2];
} else {
// 使用均值
float sum = 0.0f;
for (float val : neighbors) sum += val;
result[i] = sum / neighbors.size();
}
} else {
// 使用线性插值
int left_idx = -1, right_idx = -1;
for (int offset = 1; offset <= 5; ++offset) {
if (i - offset >= 0 && !artifact_mask[i - offset]) {
left_idx = i - offset;
break;
}
}
for (int offset = 1; offset <= 5; ++offset) {
if (i + offset < signal.size() && !artifact_mask[i + offset]) {
right_idx = i + offset;
break;
}
}
if (left_idx >= 0 && right_idx >= 0) {
float weight = static_cast<float>(i - left_idx) / (right_idx - left_idx);
result[i] = signal[left_idx] * (1.0f - weight) + signal[right_idx] * weight;
} else if (left_idx >= 0) {
result[i] = signal[left_idx];
} else if (right_idx >= 0) {
result[i] = signal[right_idx];
}
}
}
}
}
// 6. 后处理:平滑修复后的信号
if (artifact_count > 0) {
std::cout << "检测到 " << artifact_count << " 个运动伪迹点,开始后处理..." << std::endl;
// 对修复区域进行轻微平滑
std::vector<float> smoothed = result;
const size_t smooth_window = static_cast<size_t>(0.05 * sample_rate); // 50ms窗口
for (size_t i = smooth_window; i < result.size() - smooth_window; ++i) {
if (artifact_mask[i]) {
float sum = 0.0f;
size_t count = 0;
for (size_t j = i - smooth_window; j <= i + smooth_window; ++j) {
if (j < result.size()) {
sum += result[j];
count++;
}
}
if (count > 0) {
smoothed[i] = sum / count;
}
}
}
result = smoothed;
}
// 7. 质量评估
float improvement_ratio = 0.0f;
if (artifact_count > 0) {
// 计算修复前后的信号质量改善
float original_variance = 0.0f, repaired_variance = 0.0f;
for (size_t i = 1; i < signal.size(); ++i) {
original_variance += std::pow(signal[i] - signal[i-1], 2);
repaired_variance += std::pow(result[i] - result[i-1], 2);
}
if (original_variance > 0) {
improvement_ratio = (original_variance - repaired_variance) / original_variance;
}
}
std::cout << "运动伪迹检测和去除完成" << std::endl;
std::cout << "检测到的伪迹点数量: " << artifact_count << std::endl;
std::cout << "信号质量改善比例: " << (improvement_ratio * 100) << "%" << std::endl;
return result;
}

View File

@ -1,132 +0,0 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>
#include <random>
// 生成包含运动伪迹的测试信号
std::vector<float> generate_test_signal(int sample_rate, float duration) {
int num_samples = static_cast<int>(sample_rate * duration);
std::vector<float> signal(num_samples);
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<float> noise(0.0f, 0.05f);
for (int i = 0; i < num_samples; ++i) {
float t = static_cast<float>(i) / sample_rate;
// 基础信号
float base = 0.5 * sin(2 * M_PI * 1.0 * t);
// 运动伪迹
float artifact = 0.0f;
if (i % 500 == 0) { // 每500个样本添加伪迹
artifact = 0.8f * exp(-std::pow((t - static_cast<int>(t)) * 10, 2));
}
signal[i] = base + artifact + noise(gen);
}
return signal;
}
// 简化的增强版运动伪迹检测
std::vector<float> remove_motion_artifacts_simple(const std::vector<float>& signal, double sample_rate) {
if (signal.empty()) return signal;
std::vector<float> result = signal;
const size_t window_size = static_cast<size_t>(0.5 * sample_rate);
if (signal.size() < window_size) return result;
std::vector<bool> artifact_mask(signal.size(), false);
// 多尺度检测
for (size_t i = window_size; i < signal.size(); ++i) {
std::vector<float> window;
for (size_t j = i - window_size; j < i; ++j) {
window.push_back(signal[j]);
}
float sum = 0.0f, sum_sq = 0.0f;
for (float val : window) {
sum += val;
sum_sq += val * val;
}
float mean = sum / window_size;
float variance = (sum_sq / window_size) - (mean * mean);
if (variance > 1e-6f) {
float std_dev = std::sqrt(variance);
float current = signal[i];
float z_score = std::abs(current - mean) / (std_dev + 1e-6f);
if (z_score > 4.0f) {
artifact_mask[i] = true;
}
}
}
// 修复伪迹
size_t count = 0;
for (size_t i = 0; i < signal.size(); ++i) {
if (artifact_mask[i]) {
count++;
// 使用邻域中值
std::vector<float> neighbors;
for (int offset = -2; offset <= 2; ++offset) {
int idx = static_cast<int>(i) + offset;
if (idx >= 0 && idx < static_cast<int>(signal.size()) && !artifact_mask[idx]) {
neighbors.push_back(signal[idx]);
}
}
if (!neighbors.empty()) {
std::sort(neighbors.begin(), neighbors.end());
result[i] = neighbors[neighbors.size() / 2];
}
}
}
std::cout << "检测到 " << count << " 个运动伪迹点" << std::endl;
return result;
}
// 保存信号到CSV
void save_to_csv(const std::vector<float>& signal, const std::string& filename, double sample_rate) {
std::ofstream file(filename);
if (!file.is_open()) return;
file << "Time(s),Amplitude\n";
for (size_t i = 0; i < signal.size(); ++i) {
float time = static_cast<float>(i) / sample_rate;
file << time << "," << signal[i] << "\n";
}
file.close();
}
int main() {
std::cout << "=== 增强版运动伪迹检测测试 ===" << std::endl;
const int sample_rate = 100;
const float duration = 5.0f;
// 生成测试信号
std::vector<float> original = generate_test_signal(sample_rate, duration);
std::cout << "生成测试信号,长度: " << original.size() << " 样本" << std::endl;
// 应用运动伪迹检测和去除
std::vector<float> cleaned = remove_motion_artifacts_simple(original, sample_rate);
// 保存结果
save_to_csv(original, "original_with_artifacts.csv", sample_rate);
save_to_csv(cleaned, "cleaned_signal.csv", sample_rate);
std::cout << "测试完成结果已保存到CSV文件" << std::endl;
return 0;
}

View File

@ -1,339 +0,0 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>
#include <random>
#include <algorithm>
// 模拟PPG信号生成函数包含运动伪迹
std::vector<float> generate_test_ppg_with_artifacts(int sample_rate, float duration_seconds) {
int num_samples = static_cast<int>(sample_rate * duration_seconds);
std::vector<float> signal(num_samples);
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<float> noise_dist(0.0f, 0.05f);
std::uniform_real_distribution<float> artifact_dist(0.0f, 1.0f);
for (int i = 0; i < num_samples; ++i) {
float t = static_cast<float>(i) / sample_rate;
// 基础PPG信号心率约60bpm
float ppg_component = 0.5 * sin(2 * M_PI * 1.0 * t);
// 呼吸调制
float respiration = 0.1 * sin(2 * M_PI * 0.2 * t);
// 基线漂移
float baseline_drift = 0.05 * sin(2 * M_PI * 0.01 * t);
// 高频噪声
float high_freq_noise = 0.02 * sin(2 * M_PI * 10.0 * t) +
0.02 * sin(2 * M_PI * 15.0 * t);
// 运动伪迹(随机出现)
float motion_artifact = 0.0f;
if (artifact_dist(gen) < 0.01f) { // 1%概率出现运动伪迹
float artifact_type = artifact_dist(gen);
if (artifact_type < 0.3f) {
// 尖峰伪迹
motion_artifact = 0.8f * exp(-std::pow((t - static_cast<int>(t)) * 10, 2));
} else if (artifact_type < 0.6f) {
// 基线跳跃
motion_artifact = 0.3f * (artifact_dist(gen) - 0.5f);
} else {
// 高频振荡
motion_artifact = 0.2f * sin(2 * M_PI * 25.0 * t) * exp(-std::pow((t - static_cast<int>(t)) * 5, 2));
}
}
// 组合所有成分
signal[i] = ppg_component + respiration + baseline_drift + high_freq_noise + motion_artifact + noise_dist(gen);
}
return signal;
}
// 简化的增强版运动伪迹检测算法(用于测试)
std::vector<float> enhanced_motion_artifact_removal(const std::vector<float>& signal, double sample_rate) {
if (signal.empty()) return signal;
std::vector<float> result = signal;
const size_t min_window_size = static_cast<size_t>(0.1 * sample_rate);
if (signal.size() < min_window_size) return result;
// 多尺度检测窗口
std::vector<size_t> window_sizes = {
static_cast<size_t>(0.1 * sample_rate),
static_cast<size_t>(0.5 * sample_rate),
static_cast<size_t>(1.0 * sample_rate)
};
std::vector<bool> artifact_mask(signal.size(), false);
// 统计特征检测
for (size_t ws : window_sizes) {
if (signal.size() < ws) continue;
for (size_t i = ws; i < signal.size(); ++i) {
std::vector<float> window_data;
for (size_t j = i - ws; j < i; ++j) {
window_data.push_back(signal[j]);
}
// 计算统计特征
float sum = 0.0f, sum_sq = 0.0f;
for (float val : window_data) {
sum += val;
sum_sq += val * val;
}
float mean = sum / ws;
float variance = (sum_sq / ws) - (mean * mean);
if (variance > 1e-6f) {
float std_dev = std::sqrt(variance);
float current_val = signal[i];
float z_score = std::abs(current_val - mean) / (std_dev + 1e-6f);
// 检测异常值
if (z_score > 4.0f) {
artifact_mask[i] = true;
}
// 梯度异常检测
if (i > 0) {
float gradient = std::abs(current_val - signal[i-1]);
float avg_gradient = 0.0f;
for (size_t j = 1; j < std::min(ws, i); ++j) {
avg_gradient += std::abs(signal[i-j] - signal[i-j-1]);
}
avg_gradient /= std::min(ws, i);
if (gradient > 3.0f * avg_gradient) {
artifact_mask[i] = true;
}
}
}
}
}
// 形态学检测
for (size_t i = 2; i < signal.size() - 2; ++i) {
float current = signal[i];
float prev = signal[i-1];
float next = signal[i+1];
// 尖峰检测
if ((current > prev && current > next &&
current - prev > 2.0f * std::abs(next - prev)) ||
(current < prev && current < next &&
prev - current > 2.0f * std::abs(next - prev))) {
artifact_mask[i] = true;
}
}
// 智能修复
size_t artifact_count = 0;
for (size_t i = 0; i < signal.size(); ++i) {
if (artifact_mask[i]) {
artifact_count++;
// 使用中值插值
std::vector<float> neighbors;
for (int offset = -2; offset <= 2; ++offset) {
int idx = static_cast<int>(i) + offset;
if (idx >= 0 && idx < static_cast<int>(signal.size()) && !artifact_mask[idx]) {
neighbors.push_back(signal[idx]);
}
}
if (!neighbors.empty()) {
if (neighbors.size() >= 3) {
std::sort(neighbors.begin(), neighbors.end());
result[i] = neighbors[neighbors.size() / 2];
} else {
float sum = 0.0f;
for (float val : neighbors) sum += val;
result[i] = sum / neighbors.size();
}
}
}
}
std::cout << "检测到 " << artifact_count << " 个运动伪迹点" << std::endl;
return result;
}
// 计算信号质量指标
struct SignalQualityMetrics {
float snr_db;
float variance;
float peak_to_peak;
float artifact_ratio;
};
SignalQualityMetrics calculate_signal_quality(const std::vector<float>& signal, double sample_rate) {
SignalQualityMetrics metrics;
if (signal.empty()) {
metrics.snr_db = 0.0f;
metrics.variance = 0.0f;
metrics.peak_to_peak = 0.0f;
metrics.artifact_ratio = 0.0f;
return metrics;
}
// 计算基本统计量
float sum = 0.0f, sum_sq = 0.0f;
float min_val = signal[0], max_val = signal[0];
for (float val : signal) {
sum += val;
sum_sq += val * val;
min_val = std::min(min_val, val);
max_val = std::max(max_val, val);
}
float mean = sum / signal.size();
metrics.variance = (sum_sq / signal.size()) - (mean * mean);
metrics.peak_to_peak = max_val - min_val;
// 计算SNR
float signal_power = 0.0f;
float noise_power = 0.0f;
for (float val : signal) {
signal_power += std::pow(val - mean, 2);
}
signal_power /= signal.size();
for (size_t i = 1; i < signal.size(); ++i) {
float diff = signal[i] - signal[i-1];
noise_power += diff * diff;
}
noise_power /= (signal.size() - 1);
if (noise_power > 1e-6f) {
metrics.snr_db = 10.0f * std::log10(signal_power / noise_power);
} else {
metrics.snr_db = 0.0f;
}
// 估算伪迹比例(通过异常梯度检测)
size_t artifact_count = 0;
for (size_t i = 1; i < signal.size(); ++i) {
float gradient = std::abs(signal[i] - signal[i-1]);
if (gradient > 3.0f * std::sqrt(metrics.variance)) {
artifact_count++;
}
}
metrics.artifact_ratio = static_cast<float>(artifact_count) / signal.size();
return metrics;
}
// 保存信号到CSV文件
void save_signal_to_csv(const std::vector<float>& signal, const std::string& filename, double sample_rate) {
std::ofstream file(filename);
if (!file.is_open()) {
std::cerr << "无法创建文件: " << filename << std::endl;
return;
}
file << "Time(s),Amplitude\n";
for (size_t i = 0; i < signal.size(); ++i) {
float time = static_cast<float>(i) / sample_rate;
file << time << "," << signal[i] << "\n";
}
file.close();
std::cout << "信号已保存到: " << filename << std::endl;
}
int main() {
std::cout << "=== 增强版运动伪迹检测和去除算法测试 ===" << std::endl;
// 测试参数
const int sample_rate = 100; // 100Hz采样率
const float duration = 10.0f; // 10秒数据
std::cout << "采样率: " << sample_rate << "Hz" << std::endl;
std::cout << "信号长度: " << duration << "" << std::endl;
// 1. 生成包含运动伪迹的测试信号
std::cout << "\n1. 生成测试信号..." << std::endl;
std::vector<float> original_signal = generate_test_ppg_with_artifacts(sample_rate, duration);
std::cout << "测试信号生成完成,长度: " << original_signal.size() << " 样本" << std::endl;
// 2. 计算原始信号质量
std::cout << "\n2. 分析原始信号质量..." << std::endl;
SignalQualityMetrics original_metrics = calculate_signal_quality(original_signal, sample_rate);
std::cout << "原始信号质量指标:" << std::endl;
std::cout << " SNR: " << original_metrics.snr_db << " dB" << std::endl;
std::cout << " 方差: " << original_metrics.variance << std::endl;
std::cout << " 峰峰值: " << original_metrics.peak_to_peak << std::endl;
std::cout << " 伪迹比例: " << (original_metrics.artifact_ratio * 100) << "%" << std::endl;
// 3. 应用运动伪迹检测和去除
std::cout << "\n3. 应用增强版运动伪迹检测和去除..." << std::endl;
std::vector<float> cleaned_signal = enhanced_motion_artifact_removal(original_signal, sample_rate);
// 4. 计算处理后信号质量
std::cout << "\n4. 分析处理后信号质量..." << std::endl;
SignalQualityMetrics cleaned_metrics = calculate_signal_quality(cleaned_signal, sample_rate);
std::cout << "处理后信号质量指标:" << std::endl;
std::cout << " SNR: " << cleaned_metrics.snr_db << " dB" << std::endl;
std::cout << " 方差: " << cleaned_metrics.variance << std::endl;
std::cout << " 峰峰值: " << cleaned_metrics.peak_to_peak << std::endl;
std::cout << " 伪迹比例: " << (cleaned_metrics.artifact_ratio * 100) << "%" << std::endl;
// 5. 计算改善效果
std::cout << "\n5. 改善效果分析..." << std::endl;
float snr_improvement = cleaned_metrics.snr_db - original_metrics.snr_db;
float variance_reduction = (original_metrics.variance - cleaned_metrics.variance) / original_metrics.variance * 100;
float artifact_reduction = (original_metrics.artifact_ratio - cleaned_metrics.artifact_ratio) / original_metrics.artifact_ratio * 100;
std::cout << "改善效果:" << std::endl;
std::cout << " SNR改善: " << snr_improvement << " dB" << std::endl;
std::cout << " 方差减少: " << variance_reduction << "%" << std::endl;
std::cout << " 伪迹减少: " << artifact_reduction << "%" << std::endl;
// 6. 保存结果
std::cout << "\n6. 保存结果..." << std::endl;
save_signal_to_csv(original_signal, "original_signal_with_artifacts.csv", sample_rate);
save_signal_to_csv(cleaned_signal, "cleaned_signal.csv", sample_rate);
// 7. 生成对比报告
std::ofstream report("motion_artifact_removal_report.txt");
if (report.is_open()) {
report << "=== 运动伪迹检测和去除算法测试报告 ===" << std::endl;
report << "测试时间: " << std::time(nullptr) << std::endl;
report << "采样率: " << sample_rate << "Hz" << std::endl;
report << "信号长度: " << duration << "" << std::endl;
report << "\n原始信号质量:" << std::endl;
report << " SNR: " << original_metrics.snr_db << " dB" << std::endl;
report << " 方差: " << original_metrics.variance << std::endl;
report << " 峰峰值: " << original_metrics.peak_to_peak << std::endl;
report << " 伪迹比例: " << (original_metrics.artifact_ratio * 100) << "%" << std::endl;
report << "\n处理后信号质量:" << std::endl;
report << " SNR: " << cleaned_metrics.snr_db << " dB" << std::endl;
report << " 方差: " << cleaned_metrics.variance << std::endl;
report << " 峰峰值: " << cleaned_metrics.peak_to_peak << std::endl;
report << " 伪迹比例: " << (cleaned_metrics.artifact_ratio * 100) << "%" << std::endl;
report << "\n改善效果:" << std::endl;
report << " SNR改善: " << snr_improvement << " dB" << std::endl;
report << " 方差减少: " << variance_reduction << "%" << std::endl;
report << " 伪迹减少: " << artifact_reduction << "%" << std::endl;
report.close();
std::cout << "测试报告已保存到: motion_artifact_removal_report.txt" << std::endl;
}
std::cout << "\n=== 测试完成 ===" << std::endl;
std::cout << "请检查生成的CSV文件和测试报告" << std::endl;
return 0;
}

View File

@ -1,123 +0,0 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>
// 模拟PPG信号生成函数
std::vector<float> generate_test_ppg_signal(int sample_rate, float duration_seconds) {
int num_samples = static_cast<int>(sample_rate * duration_seconds);
std::vector<float> signal(num_samples);
for (int i = 0; i < num_samples; ++i) {
float t = static_cast<float>(i) / sample_rate;
// 生成包含多个频率成分的测试信号
float ppg_component = 0.5 * sin(2 * M_PI * 1.2 * t); // 1.2Hz PPG信号
float noise_component = 0.1 * sin(2 * M_PI * 50.0 * t); // 50Hz工频干扰
float high_freq_noise = 0.05 * sin(2 * M_PI * 100.0 * t); // 100Hz高频噪声
signal[i] = ppg_component + noise_component + high_freq_noise;
}
return signal;
}
// 简化的陷波滤波器实现(用于测试)
std::vector<float> simple_notch_filter(const std::vector<float>& input, double sample_rate,
double target_freq, double bandwidth) {
if (input.empty()) return {};
// 检查采样率和目标频率的合理性
if (sample_rate <= 0 || target_freq <= 0) {
std::cout << "警告: 采样率或目标频率无效,返回原始信号" << std::endl;
return input;
}
// 检查目标频率是否接近奈奎斯特频率
const double nyquist_freq = sample_rate / 2.0;
if (target_freq >= nyquist_freq * 0.8) {
std::cout << "警告: 目标频率 " << target_freq << "Hz 接近奈奎斯特频率 " << nyquist_freq << "Hz跳过陷波滤波" << std::endl;
return input;
}
// 使用带阻滤波替代陷波滤波
std::vector<float> output = input;
const double low_cutoff = target_freq - bandwidth/2;
const double high_cutoff = target_freq + bandwidth/2;
// 简单的带阻滤波实现
for (size_t i = 2; i < output.size(); ++i) {
// 简单的移动平均滤波
output[i] = (input[i] + input[i-1] + input[i-2]) / 3.0f;
}
return output;
}
// 保存信号到CSV文件
void save_signal_to_csv(const std::vector<float>& signal, const std::string& filename, double sample_rate) {
std::ofstream file(filename);
if (!file.is_open()) {
std::cerr << "无法创建文件: " << filename << std::endl;
return;
}
file << "Time(s),Amplitude\n";
for (size_t i = 0; i < signal.size(); ++i) {
float time = static_cast<float>(i) / sample_rate;
file << time << "," << signal[i] << "\n";
}
file.close();
std::cout << "信号已保存到: " << filename << std::endl;
}
int main() {
std::cout << "=== 50Hz陷波滤波器测试程序 ===" << std::endl;
// 测试不同的采样率
std::vector<int> test_sample_rates = {50, 100, 250, 500};
for (int sample_rate : test_sample_rates) {
std::cout << "\n--- 测试采样率: " << sample_rate << "Hz ---" << std::endl;
// 生成测试信号
std::vector<float> test_signal = generate_test_ppg_signal(sample_rate, 2.0); // 2秒数据
std::cout << "生成测试信号,长度: " << test_signal.size() << " 样本" << std::endl;
// 保存原始信号
std::string original_filename = "original_signal_" + std::to_string(sample_rate) + "Hz.csv";
save_signal_to_csv(test_signal, original_filename, sample_rate);
// 测试陷波滤波
std::vector<float> filtered_signal;
if (sample_rate > 100) {
// 高采样率使用标准陷波滤波
std::cout << "使用标准陷波滤波 (49.5-50.5Hz)" << std::endl;
filtered_signal = simple_notch_filter(test_signal, sample_rate, 50.0, 1.0);
} else {
// 低采样率使用带阻滤波
std::cout << "使用带阻滤波 (45-55Hz),避免过度衰减" << std::endl;
filtered_signal = simple_notch_filter(test_signal, sample_rate, 50.0, 10.0);
}
// 保存滤波后的信号
std::string filtered_filename = "filtered_signal_" + std::to_string(sample_rate) + "Hz.csv";
save_signal_to_csv(filtered_signal, filtered_filename, sample_rate);
// 计算信号统计信息
float original_rms = 0, filtered_rms = 0;
for (float val : test_signal) original_rms += val * val;
for (float val : filtered_signal) filtered_rms += val * val;
original_rms = sqrt(original_rms / test_signal.size());
filtered_rms = sqrt(filtered_rms / filtered_signal.size());
std::cout << "原始信号RMS: " << original_rms << std::endl;
std::cout << "滤波后信号RMS: " << filtered_rms << std::endl;
std::cout << "信号保留率: " << (filtered_rms / original_rms * 100) << "%" << std::endl;
}
std::cout << "\n=== 测试完成 ===" << std::endl;
std::cout << "请检查生成的CSV文件验证滤波效果" << std::endl;
return 0;
}