You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C#的实时PPG信号峰值检测算法开发求助

PPG实时峰值检测的C#实现方案

核心算法思路

针对PPG信号的实时峰值检测,推荐采用滑动窗口+自适应阈值+斜率判定的组合方案,兼顾实时性和准确性,同时能应对基线漂移与噪声干扰:

  1. 预处理:移动平均滤波:用固定长度滑动窗口对原始信号做平滑,去除高频噪声,适合实时计算场景。
  2. 峰值判定三条件:
    • 当前点斜率由正转负(信号从上升趋势转为下降)
    • 当前点幅值高于自适应阈值(阈值基于窗口内信号的均值+倍数标准差,可动态适配信号波动)
    • 与上一个检测到的峰值保持最小时间间隔(避免误检重复峰或噪声尖峰)

C#代码实现示例

using System;
using System.Collections.Generic;

public class PpgPeakDetector
{
    // 可根据设备采样率调整的参数
    private const int WindowSize = 30; // 滑动窗口长度(假设采样率100Hz,对应0.3秒)
    private const int MinPeakInterval = 15; // 最小峰间距(采样点数)
    private const double ThresholdMultiplier = 1.5; // 阈值为均值+1.5倍标准差

    private Queue<double> _rawSignalQueue = new Queue<double>();
    private Queue<double> _filteredSignalQueue = new Queue<double>();
    private int _samplesSinceLastPeak = 0;

    // 移动平均滤波:平滑原始信号,去除高频噪声
    private double ApplyMovingAverage(double newSample)
    {
        _rawSignalQueue.Enqueue(newSample);
        if (_rawSignalQueue.Count > WindowSize)
        {
            _rawSignalQueue.Dequeue();
        }

        double sum = 0;
        foreach (var sample in _rawSignalQueue)
        {
            sum += sample;
        }
        return sum / _rawSignalQueue.Count;
    }

    // 计算窗口内信号的均值与标准差,用于生成自适应阈值
    private (double mean, double stdDev) GetWindowStats()
    {
        if (_filteredSignalQueue.Count == 0)
            return (0, 0);

        double sum = 0;
        foreach (var val in _filteredSignalQueue)
            sum += val;
        double mean = sum / _filteredSignalQueue.Count;

        double sumSq = 0;
        foreach (var val in _filteredSignalQueue)
            sumSq += Math.Pow(val - mean, 2);
        double stdDev = Math.Sqrt(sumSq / (_filteredSignalQueue.Count - 1));

        return (mean, stdDev);
    }

    // 实时峰值检测接口:输入原始采样值,返回是否检测到峰值及峰值大小
    public bool DetectPeak(double rawSample, out double peakValue)
    {
        peakValue = 0;
        _samplesSinceLastPeak++;

        // 1. 预处理:对原始信号做滤波
        double filteredSample = ApplyMovingAverage(rawSample);
        _filteredSignalQueue.Enqueue(filteredSample);
        if (_filteredSignalQueue.Count > WindowSize)
        {
            _filteredSignalQueue.Dequeue();
        }

        // 窗口数据不足时,暂不检测
        if (_filteredSignalQueue.Count < WindowSize)
            return false;

        // 2. 判定斜率变化:当前点由上升转为下降
        var filteredArray = _filteredSignalQueue.ToArray();
        int currentPos = filteredArray.Length - 1;
        double prevSlope = filteredArray[currentPos] - filteredArray[currentPos - 1];
        double currSlope = filteredArray[currentPos - 1] - filteredArray[currentPos - 2];
        bool slopeCondition = prevSlope <= 0 && currSlope > 0;
        if (!slopeCondition)
            return false;

        // 3. 检查最小峰间距,避免误检
        if (_samplesSinceLastPeak < MinPeakInterval)
            return false;

        // 4. 检查是否超过自适应阈值
        var (mean, stdDev) = GetWindowStats();
        double threshold = mean + ThresholdMultiplier * stdDev;
        if (filteredSample < threshold)
            return false;

        // 满足所有条件,判定为峰值
        peakValue = filteredSample;
        _samplesSinceLastPeak = 0;
        return true;
    }
}

// 调用示例
public class Program
{
    public static void Main()
    {
        var detector = new PpgPeakDetector();
        // 这里替换为从PPG设备实时读取的数据流
        double[] simulatedPpgData = { 0.2, 0.3, 0.5, 0.8, 1.2, 1.0, 0.7, 0.4, 0.3, ... };
        foreach (var sample in simulatedPpgData)
        {
            if (detector.DetectPeak(sample, out double peak))
            {
                Console.WriteLine($"检测到峰值: {peak:F2}");
            }
            // 模拟采样间隔,对应设备实际采样率(比如100Hz则间隔10ms)
            System.Threading.Thread.Sleep(10);
        }
    }
}

调优建议

  • 根据PPG设备实际采样率调整WindowSize和MinPeakInterval:比如采样率200Hz时,窗口大小可设为60,最小峰间距设为30
  • 若基线漂移严重,可在预处理阶段加入差分滤波(计算当前点与前一点的差值),进一步消除基线影响
  • 阈值乘数ThresholdMultiplier可根据信号质量调整:噪声较大时适当增大,信号平稳时可减小

内容的提问来源于stack exchange,提问作者GORI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 13:25:15