Algorithm to locate local maxima

后端 未结 9 1884
有刺的猬
有刺的猬 2020-12-24 03:24

I have data that always looks something like this:

alt text http://michaelfogleman.com/static/images/chart.png

I need an algorithm to locate the three peaks.

相关标签:
9条回答
  • 2020-12-24 03:48

    As others have mentioned derivatives or comparing to local neighbors usually works for me. If you're worried about noise I can recommend median filtration as a pretty fast and reliable filtration scheme. I use it and reverse median filtration all the time to squelch noise in acoustic sensors, works great.

    0 讨论(0)
  • 2020-12-24 03:59

    I practice, I've found what works well is to use a dilation morphology operation to produce a dilated version of your sampled function (data points) then to identify local max's compare the dilated version vs. the original and anywhere where the dilated version equals the original version should be a local maximum. This works really well I find with 2D+ data (i.e. images) but since you have 1D data it may be easier just to use the differences between successive points as an approximation to the derivative.

    Note if you do use the dilation technique, the structuring element (both the size and shape) that you use in the dilation greatly determines the types of peaks you are looking for.

    Also if you have noise in your data, smooth it with a low pass filter, like a 1D Gaussian before searching.

    More info on dilation can be found here:

    here is the idea implemented in matlab: http://www.mathworks.com/matlabcentral/fileexchange/14498-local-maxima-minima

    if you don't know what dilation is: http://en.wikipedia.org/wiki/Dilation_%28morphology%29

    (its dead simple once you understand it here is a really easy explanation) http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm

    0 讨论(0)
  • 2020-12-24 03:59

    direct approach, something like this:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXN 100
    
    double smooth(double arr[], int n, int i)
    {
            double l,r,smoo;
            l = (i - 1 < 0)?arr[0]:arr[i-1];
            r = (i + 1 >= n)?arr[n-1]:arr[i+1];
            smoo = (l + 2*arr[i] + r)/4;
            return smoo;
    }
    
    void findmax(double arr[], int n)
    {
            double prev = arr[0];
            int i;
            int goup = 1;
    
            for(i = 0; i < n; i++)
            {
                    double cur = smooth(arr,n,i);
                    if(goup) {
                            if(prev > cur && i > 0) {
                                    printf("max at %d = %lf\n", i-1, arr[i-1]);
                                    goup = 0;
                            }
                    } else {
                            if(prev < cur)
                                    goup = 1;
                    }
                    prev = cur;
            }
    }
    
    int main()
    {
            double arr[MAXN] = {0,0,1,2,3,4,4,3,2,2,3,4,6,8,7,8,6,3,1,0};
            int n = 20, i;
    
            for(i = 0; i < n; i++)
                    printf("%.1lf ",arr[i]);
            printf("\n");
    
            findmax(arr,n);
            return 0;
    }
    

    output:

    0.0 0.0 1.0 2.0 3.0 4.0 4.0 3.0 2.0 2.0 3.0 4.0 6.0 8.0 7.0 8.0 6.0 3.0 1.0 0.0
    max at 6 = 4.000000
    max at 14 = 7.000000
    

    1) set state = goup: going upward the curve;
    2) if previuos value is greater than current then there was maximum:
    print it and set state to godown
    3) while in godown state wait until previous is less then current and switch to (1)

    to reduce noise use some smoothing function smooth()

    0 讨论(0)
提交回复
热议问题