133 lines
4.1 KiB
C++
133 lines
4.1 KiB
C++
|
|
#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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|