How can I calculate the peaks of this diagram?

51 Views Asked by At

I am programming a heart beat detector with the phone camera and the diagram actually works good. But I have a problem at calculating. In the picture below, I marked with red arrows, when a heart beat happened, these are the peaks of the diagram, they should count in my code.

But there are also these small peaks (and sometimes there are even more inbetween the "real peaks"), I marked those in yellow. How could I calculate that, without counting the yellow peaks?

Thanks in advance!

enter image description here

I have already tried smoothing but I guess I did it wrong, and also tried counting the last 5 values if they are positive, so it is a peak, but that was very unstable.

EDIT: The code for now:

  void _scanImage(CameraImage image) {
_actual = DateTime.now();

_avgRedValue = image.planes.first.bytes.reduce((value, element) => value + element) / image.planes.first.bytes.length;

if (_data.length >= _displayLength) {
  _data.removeAt(0);
}

setState(() {
  _data.add(Value(_actual, 255 - _avgRedValue));

  if (_data.length >= 7) {
    int lastIndex = _data.length - 1;
    List<double> last7Values = _data
        .sublist(lastIndex - 5, lastIndex)
        .map((value) => value.value)
        .toList();
    double lastValue = _data[lastIndex].value;
    double previousValue = _data[lastIndex - 1].value;

    if (lastValue > previousValue && lastValue > _data[lastIndex - 2].value &&
        _isIncreasing(last7Values)) {
      // Potential peak detected
      peakValues.add(lastValue);
    } else if (peakValues.isNotEmpty && lastValue < previousValue) {
      // Heartbeat detected
      double heartbeatValue = peakValues.reduce((a, b) => a > b ? a : b);
      peakValues.clear();
      int beatNow = DateTime.now().millisecondsSinceEpoch;

      if(previous != 0) {
      }
        if(beatNow - previous > 500){
      print('Heartbeat detected: $heartbeatValue');

      heartbeatCount++;

     
      }

    }


  }
});
  }

  bool _isIncreasing(List<double> values) {
if (values.length < 2) {
  return false;
}

for (int i = 1; i < values.length; i++) {
  if (values[i] <= values[i - 1]) {
    return false;
  }
}

return true;
  }
1

There are 1 best solutions below

0
Randal Schwartz On

Isn't it just, for any given three consecutive values a, b, and c, that a is less than b and b is greater than c? That can't be that hard to recognize in a list.