Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
|
filt [2026/02/27 12:11] root |
filt [2026/02/27 13:46] (текущий) root [Огибающие фильтры] |
||
|---|---|---|---|
| Строка 13: | Строка 13: | ||
| * огибающий (по минимальному и максимальному значению). | * огибающий (по минимальному и максимальному значению). | ||
| <wrap ks> | <wrap ks> | ||
| - | Рассмотрим несколько примеров для работы с данными алгоритмами. Для удобства восприятия данных, | + | Рассмотрим несколько примеров для работы с данными алгоритмами. Для удобства восприятия данных, |
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | { | ||
| + | type: ' | ||
| + | data: { | ||
| + | labels: [], | ||
| + | datasets: [ | ||
| + | { | ||
| + | label: ' | ||
| + | borderWidth: | ||
| + | borderColor: | ||
| + | tension: | ||
| + | data: [], | ||
| + | yAxisID: | ||
| + | }, | ||
| + | { | ||
| + | label: ' | ||
| + | borderWidth: | ||
| + | borderColor: | ||
| + | tension: | ||
| + | data: [], | ||
| + | yAxisID: | ||
| + | }, | ||
| + | ], | ||
| + | }, | ||
| + | options: { | ||
| + | maintainAspectRatio: | ||
| + | scales: { | ||
| + | x: {}, | ||
| + | sig1: { | ||
| + | title: { | ||
| + | display: | ||
| + | text: ' | ||
| + | }, | ||
| + | ticks: { | ||
| + | color: '# | ||
| + | }, | ||
| + | position: | ||
| + | beginAtZero: | ||
| + | min: 0, | ||
| + | max: 100, | ||
| + | }, | ||
| + | sig2: { | ||
| + | title: { | ||
| + | display: | ||
| + | text: ' | ||
| + | }, | ||
| + | ticks: { | ||
| + | color: '# | ||
| + | }, | ||
| + | position: | ||
| + | beginAtZero: | ||
| + | min: 0, | ||
| + | max: 100, | ||
| + | }, | ||
| + | }, | ||
| + | elements: { | ||
| + | point: { | ||
| + | radius: 0, | ||
| + | }, | ||
| + | }, | ||
| + | plugins: { | ||
| + | legend: { | ||
| + | display: | ||
| + | }, | ||
| + | }, | ||
| + | }, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <wrap ks> | ||
| + | В результате получим элемент графика, | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | Далее в свойстве экрана, | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | async function main() { | ||
| + | let pointList = []; // список точек графика | ||
| + | for (let i = 0; i < 300; i++) { | ||
| + | |||
| + | // создаем точки в рабочей области графика | ||
| + | let val = Math.sin(i / 30) * 40 + 50; | ||
| + | |||
| + | // пока выведем точки только исходного графика | ||
| + | pointList.push([ i, val]); | ||
| + | } | ||
| + | |||
| + | // выведем созданный список точек на график | ||
| + | await ds.objCall(' | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <wrap ks> | ||
| + | После чего запустим проект на исполнение, | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | В данной заготовке мы видим как выглядит идеальный сигнал с нашего выдуманного датчика. В дальнейшем будем вносить в него помехи и пробовать пропустить полученный сигнал через фильтр, | ||
| + | </ | ||
| + | |||
| + | ====== Среднеарифметический фильтр ====== | ||
| + | |||
| + | <wrap ks> | ||
| + | Среднеарифметический фильтр, | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | // создаем фильтр с размерностью в 10 значений | ||
| + | let filt = ds.crtFilt(' | ||
| + | |||
| + | let pointList = []; | ||
| + | for (let i = 0; i < 300; i++) { | ||
| + | let val = Math.sin(i / 30) * 40 + 50; | ||
| + | |||
| + | // добавляем к исходному сигналу случайную помеху | ||
| + | val += Math.random() * 4 - 2; | ||
| + | |||
| + | let filtVal = filt.add(val); | ||
| + | pointList.push([ i, val, filtVal ]); | ||
| + | } | ||
| + | |||
| + | await ds.objCall(' | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | В результате видим, что не смотря на то что в изначальном сигнале присутствует большое количество колебаний сигнала, | ||
| + | </ | ||
| + | |||
| + | <wrap ks> | ||
| + | Теперь рассмотрим ситуацию, | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | let filt = ds.crtFilt(' | ||
| + | |||
| + | 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(' | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | В данном случае видим что отфильтрованный сигнал все равно сильно искажен, | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | // увеличиваем размер фильтра | ||
| + | let filt = ds.crtFilt(' | ||
| + | |||
| + | 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(' | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | В результате видим, что хоть отфильтрованный график и начал принимать форму, похожую на изначальную синусоиду, | ||
| + | </ | ||
| + | |||
| + | ====== Медианный фильтр ====== | ||
| + | |||
| + | <wrap ks> | ||
| + | Иногда бывает так, что сигнал продолжительное время достаточно чисто идет, и лишь кратковременно прилетает какая-то помеха (ошибка измерения, | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | let filt = ds.crtFilt(' | ||
| + | |||
| + | 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(' | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | На графике видно, что если даже одна точка выбивается из чистого графика, | ||
| + | </ | ||
| + | |||
| + | <code javascript> | ||
| + | // используем вместо среднеарифметического, | ||
| + | let filt = ds.crtFilt(' | ||
| + | |||
| + | 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(' | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | Здесь хорошо видно, что помеха лишь незначительно исказила график (связано это с тем, что пришлось пропустить | ||
| + | </ | ||
| + | |||
| + | ====== Огибающие фильтры ====== | ||
| + | |||
| + | <wrap ks> | ||
| + | Не редко так же бывает ситуация, | ||
| + | </ | ||
| + | |||
| + | |||
| + | <code javascript> | ||
| + | // создаем огибающий фильтр по максимальному значению | ||
| + | let filt = ds.crtFilt(' | ||
| + | |||
| + | 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(' | ||
| + | </ | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | <wrap ks> | ||
| + | Так же плюс данного фильтра, | ||
| </ | </ | ||