Инструменты пользователя

Инструменты сайта


filt

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
filt [2026/02/27 12:39]
root [Среднеарифметический фильтр]
filt [2026/02/27 13:46] (текущий)
root [Огибающие фильтры]
Строка 152: Строка 152:
 </wrap> </wrap>
  
 +<wrap ks>
 +Теперь рассмотрим ситуацию, где помеха гораздо значительнее влияет на сигнал.
 +</wrap>
 +
 +<code javascript>
 +let filt = ds.crtFilt('sraf', 10);
 +
 +let pointList = [];
 +for (let i = 0; i < 300; i++) {
 +    let val = Math.sin(i / 30) * 40 + 50;
 +    
 +    // увеличиваем размер помехи
 +    val += Math.random() * 20 - 10;
 +    
 +    let filtVal = filt.add(val);
 +    pointList.push([ i, val, filtVal ]);
 +}
 +
 +await ds.objCall('График данных 1', 'addPointList', pointList);
 +</code>
 +
 +{{ :filt4.png?nolink |}}
 +
 +<wrap ks>
 +В данном случае видим что отфильтрованный сигнал все равно сильно искажен, и вряд ли с ним можно будет работать в дальнейшем. Можно попробовать увеличить размер фильтра, попытавшись сгладить большее количество точек.
 +</wrap>
 +
 +<code javascript>
 +// увеличиваем размер фильтра
 +let filt = ds.crtFilt('sraf', 50);
 +
 +let pointList = [];
 +for (let i = 0; i < 300; i++) {
 +    let val = Math.sin(i / 30) * 40 + 50;
 +    
 +    val += Math.random() * 20 - 10;
 +    
 +    let filtVal = filt.add(val);
 +    pointList.push([ i, val, filtVal ]);
 +}
 +
 +await ds.objCall('График данных 1', 'addPointList', pointList);
 +</code>
 +
 +{{ :filt5.png?nolink |}}
 +
 +<wrap ks>
 +В результате видим, что хоть отфильтрованный график и начал принимать форму, похожую на изначальную синусоиду, но при этом видно что ее амплитуда сильно меньше, так же по времени отставание достаточно значительное. В таком случае зачастую никакой фильтр уже не поможет, необходимо разбираться с первопричиной помехи.
 +</wrap>
 +
 +====== Медианный фильтр ======
 +
 +<wrap ks>
 +Иногда бывает так, что сигнал продолжительное время достаточно чисто идет, и лишь кратковременно прилетает какая-то помеха (ошибка измерения, или включился где-то контактом с большим электромагнитным импульсом), в таком случае среднеарифметический фильтр справляется уже не так хорошо.
 +</wrap>
 +
 +<code javascript>
 +let filt = ds.crtFilt('sraf', 10);
 +
 +let pointList = [];
 +for (let i = 0; i < 300; i++) {
 +    let val = Math.sin(i / 30) * 40 + 50;
 +    
 +    // добавляем кратковременную большую помеху
 +    if (i % 33 == 0) val += Math.random() * 100 - 50;
 +    
 +    let filtVal = filt.add(val);
 +    pointList.push([ i, val, filtVal ]);
 +}
 +
 +await ds.objCall('График данных 1', 'addPointList', pointList);
 +</code>
 +
 +{{ :filt6.png?nolink |}}
 +
 +<wrap ks>
 +На графике видно, что если даже одна точка выбивается из чистого графика, алгоритм среднеарифметического фильтра возмущение от нее еще видит достаточно продолжительное время. В данной ситуации хорошо работает медианный фильтр. Он, в отличие от среднеарифметического, который использует весь диапазон точек на интервале (в том числе и ту, которая с помехой), а выбирает из диапазона среднее значение из всех точек. Соответственно в данной ситуации точки с большим отклонением от остальных будут исключаться.
 +</wrap>
 +
 +<code javascript>
 +// используем вместо среднеарифметического, медианный фильтр с таким же размером
 +let filt = ds.crtFilt('median', 10);
 +
 +let pointList = [];
 +for (let i = 0; i < 300; i++) {
 +    let val = Math.sin(i / 30) * 40 + 50;
 +    
 +    if (i % 33 == 0) val += Math.random() * 100 - 50;
 +    
 +    let filtVal = filt.add(val);
 +    pointList.push([ i, val, filtVal ]);
 +}
 +
 +await ds.objCall('График данных 1', 'addPointList', pointList);
 +</code>
 +
 +{{ :filt7.png?nolink |}}
 +
 +<wrap ks>
 +Здесь хорошо видно, что помеха лишь незначительно исказила график (связано это с тем, что пришлось пропустить "бракованную" точку).
 +</wrap>
 +
 +====== Огибающие фильтры ======
 +
 +<wrap ks>
 +Не редко так же бывает ситуация, когда помеха улетает только в одну сторону относительно исходного графика. Такое часто бывает, к примеру, при периодическом пропадании связи с датчиком, и вместо показаний, получаем нулевое значение. В таких случаях хорошо отрабатывают огибающие фильтры. Их алгоритм работы похож на среднемедианный, но в отличие от него берется не среднее значение, а минимальное или максимальное на диапазоне значений (в зависимости от типа огибающего фильтра).
 +</wrap>
 +
 +
 +<code javascript>
 +// создаем огибающий фильтр по максимальному значению
 +let filt = ds.crtFilt('max', 10);
 +
 +let pointList = [];
 +for (let i = 0; i < 300; i++) {
 +    let val = Math.sin(i / 30) * 40 + 50;
 +    
 +    // эмулируем потерю сигнала
 +    if (i % 33 == 0) val = 0;
 +    
 +    let filtVal = filt.add(val);
 +    pointList.push([ i, val, filtVal ]);
 +}
 +
 +await ds.objCall('График данных 1', 'addPointList', pointList);
 +</code>
 +
 +{{ :filt8.png?nolink |}}
 +
 +<wrap ks>
 +Так же плюс данного фильтра, в отличие от рассмотренных ранее, в том, что на участке роста значений, он не имеет отставания, и четко повторяет исходный сигнал. Такой фильтр удобно использовать с данными, которые изменяются в одном направлении (растут или падают, в случае с огибающим по минимальному значению). Так же продолжительность возмущения от помехи на данном типе фильтра длится не всю продолжительность работы фильтра, а лишь на единственной точке.
 +</wrap>
  
filt.1772185182.txt.gz · Последнее изменение: 2026/02/27 12:39 — root