Документация Engee
Notebook

Фильтрация зашумленного сигнала скользящим усреднением

В этом примере показано, как при помощи блока Moving RMS осуществлять фильтрацию скользящим средним (простым и экспоненциальным). Меняя настройки блока мы получим четыре разных характера поведения фильтра.

Описание модели и фильтров

Блок Pulse Generator генерирует прямоугольные импульсы длиной в 512 временных отсчетов каждый. Блок Switch управляет переключением между верхним и нижним уровнями меандра (между 0.5 и 1.5). Мы добавляем к этому сигналу шум с математическим ожиданием 0 и дисперсией 0.001.

Для сглаживания методом скользящего окна (moving average (MA)) или КИХ-фильтром мы реализуем два режима, различающихся коэффициентом перекрытия окон. В одном случае фильтр будет делать скачок на 1 измерение, в другом на 4 измерений. Результат этих фильтров почти не будет отличаться по значению выходной величины, однако дискретизация фильтра с перекрытием 4 будет в 4 раза ниже, чем у фильтра со скачком 1.

Мы также реализуем набор БИХ-фильтров с экспоненциальным сглаживанием (exponential moving average (EMA)), для которых выставим разные весовые коэффициенты: 0.9 и 0.99. Они существенно влияют на выходной сигнал: график с меньшим значением коэффициента сглаживания (0.9) будет динамичнее реагировать как на помеху, так и на переключение сигнала между уровнями.

Подробнее про работу этих методов сглаживания и про их параметры можно почитать в справке по блоку Moving RMS.

image.png

Отдельные области модели выделены при помощи аннотаций, в которых заключена SVG-разметка.

Частота дискретизации модели

Поскольку в Engee необходимо указывать размер шага модели, работа с многоскоростными моделями требует внимательного отношения к дискретизации разных блоков. Разберем одну ситуацию. Генератор шума срабатывает в 512 раз чаще, чем генератор импульсов. Модель настроена выдавать 44100 измерений в секунду.

Если у первого по счету сглаживающего фильтра указан размер скачка сглаживающего окна равный 4, то частота дискретизации сигнала после этого фильтра будет равна (512/4)/44100, то есть 128/44100 (можно сказать, 128 отсчетов).

Но если мы захотим сделать размер скачка равным 5, то придется менять базовую частоту дискретизации модели. Действительно, на выходе такого фильтра сигнал будет иметь дискретизацию (512/5)/44100, то есть 102.4/44100 (дробное количество отсчетов). В таком случае базовая частота дискретизации модели больше не является общим делителем для частоты дискретизации всех сигналов на холсте. Для восстановления работоспособности модели ее нужно будет увеличить в 5 раз (5*44100).

Запуск модели

Запустим модель средствами программного управления и сравним результаты разных фильтров.

In [ ]:
modelName = "mvgRMSNoisyStep";
model = modelName in [m.name for m in engee.get_all_models()] ? engee.open( modelName ) : engee.load( "$(@__DIR__)/$(modelName).engee");
engee.set_param!( modelName, "StopTime"=>8 );
data = engee.run( modelName, verbose=false )
Out[0]:
Dict{String, DataFrame} with 5 entries:
  "MA - Размер скачка 4"              => 88201×2 DataFrame…
  "MA - Размер скачка 1"              => 352801×2 DataFrame…
  "EMA - Показатель сглаживания 0.9"  => 352801×2 DataFrame…
  "EMA - Показатель сглаживания 0.99" => 352801×2 DataFrame…
  "Зашумленные импульсы"              => 352801×2 DataFrame

Построим общий график:

In [ ]:
plot( data["Зашумленные импульсы"].time[1:4:end], data["Зашумленные импульсы"].value[1:4:end],
    c=5, label="Зашумленные импульсы" )
plot!( data["MA - Размер скачка 4"].time[1:4:end], data["MA - Размер скачка 4"].value[1:4:end],
    c=1, label="Размер скачка 4" )
plot!( data["MA - Размер скачка 1"].time[1:4:end], data["MA - Размер скачка 1"].value[1:4:end],
    c=2, label="Размер скачка 1" )
plot!( data["EMA - Показатель сглаживания 0.9"].time[1:4:end], data["EMA - Показатель сглаживания 0.9"].value[1:4:end],
    c=3, label="Показатель сглаживания 0.9" )
plot!( data["EMA - Показатель сглаживания 0.99"].time[1:4:end], data["EMA - Показатель сглаживания 0.99"].value[1:4:end],
    c=4, label="Показатель сглаживания 0.99" )
Out[0]:

Приблизим график, чтобы увидеть, как разные алгоритмы сглаживания отрабатывают резкую смену уровня сигнала.

In [ ]:
r1 = 65500:65800
r2 = 4 .* r1

plot( data["Зашумленные импульсы"].time[r2], data["Зашумленные импульсы"].value[r2],
       c=5, label="Зашумленные импульсы" )
plot!( data["MA - Размер скачка 4"].time[r1], data["MA - Размер скачка 4"].value[r1],
        c=1, label="Размер скачка 4" )
plot!( data["MA - Размер скачка 1"].time[r2], data["MA - Размер скачка 1"].value[r2],
        c=2, label="Размер скачка 1" )
plot!( data["EMA - Показатель сглаживания 0.9"].time[r2], data["EMA - Показатель сглаживания 0.9"].value[r2],
        c=3, label="Показатель сглаживания 0.9" )
plot!( data["EMA - Показатель сглаживания 0.99"].time[r2], data["EMA - Показатель сглаживания 0.99"].value[r2],
        c=4, label="Показатель сглаживания 0.99" )
Out[0]:

Заключение

Мы провели сравнение нескольких способов усреднения сигнала, выполненных при помощи блока Moving RMS с разными настройками и можем реализовать нужный нам алгоритм, а также объективно выбрать наилучший способ фильтрации.

Блоки, использованные в примере