Identifying and smoothing out peaks in an array

Good evening,

Is there a simple way to detect and smooth local peak or peaks in a long array and create a new array with the new value/s, but keeping the same order as the original array?

A simplified example of what I would like:

int myArray[]={2,4,6,10,8,11,12}; the culprit is 10.

Would probably end up something like:

int myResult[]={2,4,6,7,8,10,12};

Thank you.

1 Like

does not matter if that is a array or a data stream,
the idea seems to be to have

or

  • reject extreme signals

start with a code that detects that “culprit” position in array and show that code here,
this way we understand how you would define mathematically a “peak”

1 Like

You can use a moving average (simple or weighted) [affects all data].

Or if a number is a local minimum or maximum (meaning that it is less than, or greater than, each of the numbers adjacent to it) set it to the mean of the two adjacent numbers (or similar) [affects peaks and troughs only].

2 Likes

Thank you both, yes, this is the case, and this is probably the path I will follow. I don’t want to eliminate (filter out) the offending peak/trough, the element needs to remain there, albeit with its value down/up to an average between 2 or 3 adjacent values. I just have to find a formula that I can code with my limited knowledge. The peaks are only just noticeable, all I need is a way to smooth out the continuity a little.

2 Likes

Computing a basic moving average / rolling average is very simple. The trick is to pick the best window size based on your input range and desired amount of smoothing – and to use an index with % to add updated values to the window in a “rolling” way.

Here is a simple interactive sketch to let you play with rolling averages.

/**
 * 2019-10-01 rolling average (smoothing)
 * - move mouse right-left to change the size of the window (number of values)
 * - move mouse up-down to change the range of the input values
 * for related discussion see:
 * discourse.processing.org/t/identifying-and-smoothing-out-peaks-in-an-array/14331
 */

int window[];
int window_size;
int index;

void setup(){
  size(200,200);
  window = new int[width];
  window_size=1;
  index=0;
}
void draw() {  
  int x = frameCount%width;  // move to next pixel
  int y = int(random(height-mouseY));  // pick random from mouse-height range
  window_size=constrain(mouseX, 1, width);
  index = (index+1) % window_size;  // advance to next window slot
  window[index] = y;  // add value to window

  // draw random value
  stroke(0, 0, 255);
  ellipse(x, height-y, 3, 3);

  float yavg = avg(window);  // compute rolling average
  // draw random smoothed value
  stroke(255, 0, 0);
  ellipse(x, height-yavg, 3, 3);

  // draw wipe line
  stroke(0);
  line(x,0,x,height);
  stroke(255);
  line(x+1,0,x+1,height);
  // draw window size indicator
  stroke(0);
  line(0,1,width,1);
  stroke(255,0,0);
  line(0,1,mouseX,1);

}

float avg(int[] window) {
  float sum = 0;
  for (int i=0; i<window_size; i++) {
    sum+=window[i];
  }
  return sum/window_size;
}

RollingAverage--screenshot

Edit oops – removed some unused utility functions from the end.

2 Likes

Thank you so much, Jeremy. I’m now playing it, it works well. I will try to adapt it to my project.

To identify a peak I like using the centroid algorithm. For smoothing, you can explore this SO post that discusses a few options. You need to find the proper algorithm that fits the nature of your data. For instance, the moving average would act as a low pass filter, removing high frequency signals.

Kf

1 Like