一种简单查找峰值的函数实现

最近经常用到查找峰值的函数

已有的函数要不代码量比较大,要不就是逻辑比较复杂、设置的条件比较多,当然对于需要筛选出很合适的峰值来说,这些条件是必须的,对于纷繁复杂的波形中查找到你想要的那个波峰,需要慧眼; 

但是对于波形很多的数据,不需要那么繁琐的逻辑判断,根据自己的经验,写了一个代码雏形,用来查找峰值,当然后续还需要简单的加一些其他的判断,但对于我的功能已经完成,简单记录一下;主要思想是在前后一定范围内查找合适的波峰或波谷。 下面代码无法直接运行,只是程序中的一个函数。

代码如下:

    uint8_t K = 8;
    static uint8_t left_k_max = 0, right_k_max = 0, left_k_min = 0, right_k_min = 0;
    static uint32_t max_data_pos = -100, min_data_pos = 100;

    static float max_data = 0,  min_data = 0;

    sen_data_swim = data; // 向外传原始raw data
    peak_index_swim = 0;  // 向外传峰值位置
    valley_index_swim = 0;  // 向外传波谷值位置

    //mexPrintf("%d - max_data:%f, max:%d left_k_max:%d \n", g_index, max_data, max_data_pos, left_k_max);
    if (max_data < data)    
    {   
        max_data = data;
        max_data_pos = g_index;
        left_k_max = 0;
        right_k_max++;
    }
    else
    {
        left_k_max++;
        right_k_max = 0;
    }

    if (min_data > data)
    {
        min_data = data;
        min_data_pos = g_index;
        left_k_min++;
        right_k_min = 0;
    }
    else
    {
        left_k_min = 0;
        right_k_min++;
    }

    if (left_k_max == 10)
    {
        mexPrintf("send max pos:%d\n", max_data_pos);
        peak_index_swim = max_data_pos;
        max_data = data;
        left_k_max = 0;
    }

    if (right_k_min == 10)
    {
        mexPrintf("send min pos:%d\n", min_data_pos);
        valley_index_swim = min_data_pos;
        min_data = data;
        right_k_min = 0;
    }

简单示意图

优化了一些条件,将无用的波峰过滤掉

    uint8_t K = 10;
    static uint8_t right_k_max_ = 0, left_k_max_ = 0, left_k_min = 0, right_k_min = 0;
    static uint32_t max_data_pos = -100, min_data_pos = 100;
    static uint32_t pre_max_data_pos = 0;
    static float max_data = 0, min_data = 0;
    static float pre_max_data = 0, pre_min_data = 0;
    static bool need_to_find_peak = false;

    sen_data_swim = data;
    peak_index_swim = 0;
    valley_index_swim = 0;

    //mexPrintf("%d - max_data:%f, max:%d right_k_max_:%d \n", g_index, max_data, max_data_pos, right_k_max_);
    if (max_data < data)
    {
        pre_max_data = max_data;
        pre_max_data_pos = max_data_pos;

        max_data = data;
        max_data_pos = g_index;
        right_k_max_ = 0;
        left_k_max_++;
    }
    else
    {
        right_k_max_++;
        left_k_max_ = 0;
    }

    if (min_data > data)
    {
        //
        min_data = data;

        min_data_pos = g_index;
        left_k_min++;
        right_k_min = 0;
    }
    else
    {
        left_k_min = 0;
        right_k_min++;
    }

    if (right_k_max_ == K)
    {
        mexPrintf("%d,send max pos:%d, bool:%d, max:%f min:%f,pre-min:%f \n", g_index, max_data_pos, need_to_find_peak, max_data, min_data, pre_min_data);
        if (need_to_find_peak == true)
        {
            //if (max_data - min_data > 5 && g_index - max_data_pos < 50)
            //if(max_data - min_data > 5)
            if (max_data - pre_min_data > 5)
            {
                peak_index_swim = max_data_pos;

                need_to_find_peak = false;
            }

            //max_data = data;
            //right_k_max_ = 0;            
        }

        max_data = data;
        right_k_max_ = 0;
    }

    if (right_k_min == K)
    {
        if (need_to_find_peak == false)
        {
            pre_min_data = min_data;

            valley_index_swim = min_data_pos;
            min_data = data;
            right_k_min = 0;

            need_to_find_peak = true;
        }

        mexPrintf("send min pos:%d, mini:%f, pre-min:%f \n", min_data_pos, min_data, pre_min_data);
        //pre_min_data = min(min_data, data);        

    }

    if (right_k_min == 20) /* can find valley*/
    {
        need_to_find_peak = false;
    }

    if (right_k_max_ == 20)
    {
        need_to_find_peak = true;
    }

版本3,发现上面的版本还是针对某些情况不能包含,又重新写了一版

void FindPeak(float data)
{
    uint8_t K = 10;
    static uint8_t left_k_max = 0, right_k_max = 0, left_k_min = 0, right_k_min = 0;
    static uint8_t pre_left_k_max = 0, pre_right_k_max = 0, pre_left_k_min = 0;
    static uint32_t max_data_pos = 0, min_data_pos = 0;
    static uint32_t pre_right_k_max_pos = 0, pre_left_k_min_pos = 0;
    static float pre_data = 0;

    sen_data_swim = data;
    peak_index_swim = 0;
    valley_index_swim = 0;

    if (data > pre_data) /* up*/
    {
        right_k_max++;

        if (max_data < data)
        {
            max_data = data;
            max_data_pos = g_index;
        } 

        if (right_k_max >= K)
        {
            if (right_k_max == K)
            {
                left_k_max = 0;
                valley_index_swim = min_data_pos;
            }
            else
            {
                min_data = data;
            }
        }
    }

    if (data < pre_data) /* down */
    {
        left_k_max++;

        if (min_data > data)
        {
            min_data = data;
            min_data_pos = g_index;
        }

        if (left_k_max >= K)
        {
            if (left_k_max == K) /* save the maximum */
            {
                right_k_max = 0;
                peak_index_swim = max_data_pos;
            }
            else
            {
                max_data = data; /* update the minimum */
            }            
        }
    }
 
    pre_data = data;
}

效果

..

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚努力的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值