最近经常用到查找峰值的函数
已有的函数要不代码量比较大,要不就是逻辑比较复杂、设置的条件比较多,当然对于需要筛选出很合适的峰值来说,这些条件是必须的,对于纷繁复杂的波形中查找到你想要的那个波峰,需要慧眼;
但是对于波形很多的数据,不需要那么繁琐的逻辑判断,根据自己的经验,写了一个代码雏形,用来查找峰值,当然后续还需要简单的加一些其他的判断,但对于我的功能已经完成,简单记录一下;主要思想是在前后一定范围内查找合适的波峰或波谷。 下面代码无法直接运行,只是程序中的一个函数。
代码如下:
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;
}
效果
..