Для следующего сигнала:
Если вы берете абсолютное значение разности между двумя последовательными выборками, вы получите:
Этого недостаточно для того, чтобы однозначно отличить от незначительных "неподдерживаемых" нарушений. Но если вы тогда возьмете простую скользящую сумму (негерметичный интегратор) из abs-дифференциалов. Здесь использовалось окно шириной 4 различных образца:
Скользящее среднее вводит задержку или фазовый сдвиг, который в случаях, когда данные сохраняются, а обработка не в реальном времени , может быть легко компенсирована вычитанием половины ширины окна из времени:
Для обработки в реальном времени, если задержка является критической, может быть целесообразен более сложный БИХ-фильтр. В любом случае из этих данных может быть выбран четкий порог.
В коде для вышеуказанного набора данных:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
static int32_t dataset[] = { 0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,3,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
0,-10,-15,-5,20,25,50,-10,-20,-30,0,30,5,-5,
0,0,5,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,1,0,0,0,0,6,0,0,0,0,0,0,0} ;
#define DATA_LEN (sizeof(dataset)/sizeof(*dataset))
#define WINDOW_WIDTH 4
#define THRESHOLD 15
int main()
{
uint32_t window[WINDOW_WIDTH] = {0} ;
int window_index = 0 ;
int window_sum = 0 ;
bool spike = false ;
for( int s = 1; s < DATA_LEN ; s++ )
{
uint32_t diff = abs( dataset[s] - dataset[s-1] ) ;
window_sum -= window[window_index] ;
window[window_index] = diff ;
window_index++ ;
window_index %= WINDOW_WIDTH ;
window_sum += diff ;
if( !spike && window_sum >= THRESHOLD )
{
spike = true ;
printf( "Spike START @ %d\n", s - WINDOW_WIDTH / 2 ) ;
}
else if( spike && window_sum < THRESHOLD )
{
spike = false ;
printf( "Spike END @ %d\n", s - WINDOW_WIDTH / 2 ) ;
}
}
return 0;
}
Вывод:
Spike START @ 66
Spike END @ 82
https://onlinegdb.com/ryEw69jJH
Сравнение исходных данных с порогом обнаружения дает:
Для ваших реальных данных вам нужно будет выбрать подходящую ширину окна и порог, чтобы получить желаемый результат, оба из которых будут зависеть от ширины полосы и амплитуды помех, которые вы хотите обнаружить.
Также вам может потребоваться защита от арифметического переполнения, если ваши выборки имеют достаточную величину. Они должны быть меньше 2 32 / ширина окна , чтобы гарантировать отсутствие переполнения в интеграторе. В качестве альтернативы вы можете использовать число с плавающей точкой или uint64_t
для типа window
или добавить код для обработки saturation .