Выходное начальное/конечное значение фильтра нижних частот Matlab

У меня есть сигнал с нежелательной колеблющейся несущей, показанной синей кривой. Я сделал фильтр нижних частот (баттерворт 5-го порядка) и применил его с функцией filtfilt, а нижний отфильтрованный результат — красная кривая.

[b,a] = butter(5,.7);
y = filtfilt(b,a,y);

введите описание изображения здесьКрасная кривая от значения x 500 до конца - это именно то, что я хотел, однако начальное колебание все еще там. Похоже, что функция фильтра пытается сопоставить начальное/конечное значение входа и выхода фильтра, поэтому колебание сохраняется. Есть ли способ не соответствовать начальному значению, чтобы я мог получить плавный вывод без каких-либо колебаний?

Обновление: я думаю, что мой вопрос не был ясен. Я хочу что-то вроде черной кривой (рисунок от руки): полностью удалить колебание и НЕ соответствовать начальному значению. Как я могу это сделать? введите здесь описание изображения


person LWZ    schedule 30.12.2012    source источник


Ответы (4)


Столкнувшись с этой проблемой, я часто заканчиваю тем, что создаю начальный сигнал, который предшествует отфильтрованному сигналу.

Для фильтра нижних частот это относительно простая задача, но зависит от исходного сигнала. Моя первоначальная попытка состояла бы в том, чтобы отразить часть сигнала относительно источника:

[b,a] = butter(5,.7);
N = 50; % change this to suit your needs
    yNew = filtfilt(b,a,[y(N:-1:1);y];
yNew = yNew(N+1:end);

Это гарантирует, что запуск будет минимальным, и вы сможете «браться за дело».

person Rasman    schedule 01.01.2013
comment
Возможно, стоит также добавить сигнал в конце. Кроме того, вы можете использовать для этой цели функцию padarray, у нее есть несколько интересных вариантов заполнения. - person Shai; 01.01.2013

Короткий ответ: то, о чем вы просите, невозможно.

Всем фильтрам требуется некоторое время, чтобы «разогреться» — это известно как «время нарастания» фильтра. Это происходит из-за того, что фильтр nпорядка выполняет средневзвешенное значение последних n отсчетов, а при первом запуске сигнала эта задержка отсчетов недоступна.

Фильтр, который у вас есть, на самом деле имеет довольно хорошее время нарастания — требуется всего около 10 сэмплов, чтобы начать правильно отслеживать вход.

Возникающие колебания известны как «перерегулирование» — при проектировании фильтра существует компромисс между временем нарастания и перерегулированием, у вас не может быть быстрого времени нарастания и отсутствия перерегулирования. Статья в Википедии о демпфировании может быть для вас хорошим ресурсом.

person Fabian Tamp    schedule 30.12.2012
comment
Я понимаю. Это имеет смысл. Так что фильтры нижних частот не дадут мне того, что мне нужно. Тогда какие еще методы могут убрать мне это колебание? Должен быть способ, верно? Это просто математическая вещь. - person LWZ; 30.12.2012
comment
Вы можете избавиться от осцилляции, если резко задемпфируете свой фильтр, но это уменьшит время нарастания. - person Fabian Tamp; 31.12.2012
comment
Спасибо, но я думаю, что мой вопрос был вам не ясен или, может быть, вообще не корректен. Сейчас я его обновил и хочу что-то вроде черной кривой, полностью убрать колебание и оставить только линию тренда. Критическая влажность все равно даст мне первоначальный подъем. - person LWZ; 31.12.2012

Читая предыдущие ответы и комментарии, кажется, что фильтрация - это не совсем искомый ответ на этот конкретный вопрос.

Рассматривали ли вы соответствие сигнала какой-либо параметрической кривой? Поскольку искомая кривая лежит среди сигнала (без «выбросов»), кажется, что подгонка методом наименьших квадратов может работать достаточно хорошо.

% assuming y is your signal
% fit polynomial of degree Deg
Deg = 5; 
x = linspace(0,1, numel(y));
p = polyfit( x, y, Deg );
figure('Name','fit poly');
plot( y, '-+b');
hold all;
plot( polyval( p, x ), ':k', 'LineWidth', 1.2 );

В этом примере я использовал от polyfit до Deg=5, но вы можете рассмотреть разные функции и разные степени.

Вы можете найти fit полезным инструментом.

person Shai    schedule 31.12.2012

Попробуйте сголай фильтровать (порядка 1 должно хватить) перед применением масляного фильтра. Sgolayfilter подбирает начальные точки с лежащей в их основе полиномиальной аппроксимацией (линия для порядка 1). См. пример с чем-то похожим на ваши данные

tt=0:1000;
toto=cos(.3*tt).*cos(tt*pi/4000)-tt/500+sin(pi*tt/1000);
[B,A]=butter(4,.02);
plot(tt,toto,tt,filtfilt(B,A,toto),'r',tt,filtfilt(B,A,sgolayfilt(toto,1,51)),'k');

Надеюсь, что еще может помочь.

person R. Sabot    schedule 04.04.2013