medical_SDK/test_motion_artifact.cpp

133 lines
4.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}