Підбір правильного фільтра для даних акселерометра


28

Я досить новачок у DSP і провів деякі дослідження можливих фільтрів для згладжування даних акселерометра в python. Приклад типу даних, які я відчуваю, можна побачити на наступному зображенні:

Дані акселерометра

По суті, я шукаю поради, як згладити ці дані, щоб з часом перетворити їх у швидкість та переміщення. Я розумію, що акселерометри з мобільних телефонів надзвичайно галасливі.

Я не думаю, що я можу використовувати фільтр Kalman на даний момент, тому що я не можу отримати пристрій для посилання на шум, що видається даними (я читав, що його важливо, щоб розмістити пристрій рівним і знайти кількість шуму від цих показань?)

FFT дав кілька цікавих результатів. Однією з моїх спроб було FFT сигнал прискорення, а потім надавати низькі частоти, щоб мати абсолютне значення FFT 0. Тоді я використав амега арифметичний і зворотний FFT, щоб отримати графік швидкості. Результати були такими:

Відфільтрований сигнал

Це хороший шлях для речей? Я намагаюся зняти загальний шумний характер сигналу, але очевидні піки, такі як приблизно за 80 секунд, потрібно визначити.

Я також втомився від використання фільтрів низьких частот за оригінальними даними акселерометра, який зробив велику роботу з його згладжуванням, але я не дуже впевнений, куди подітися. Будь-які вказівки щодо того, куди поїхати звідси, були б дуже корисними!

EDIT: Трохи коду:

for i in range(len(fz)): 
    testing = (abs(Sz[i]))/Nz

    if fz[i] < 0.05:
        Sz[i]=0

Velfreq = []
Velfreqa = array(Velfreq)
Velfreqa = Sz/(2*pi*fz*1j)
Veltimed = ifft(Velfreqa)
real = Veltimed.real

Таким чином, Ive здійснив FFT за моїми даними акселерометра, даючи Sz, відфільтровував високі частоти, використовуючи простий фільтр цегляної стіни (я знаю, що це не ідеально). Тоді я використовую арифметику омеги на FFT даних. Також дуже дякую datageist за додавання моїх зображень у мій пост :)


Ласкаво просимо до DSP! Чи є червона крива на вашому другому знімку "згладженою" версією вихідних (зелених) даних?
Phonon

Червона крива - це (сподіваємось!) - крива швидкості, породжена з fft, з подальшим фільтруванням, а потім арифметикою омеги (ділення на 2 * pi f j), наступною за інв. fft
Michael M

1
Можливо, якщо ви додасте більш точний математичний вираз або псевдокод для того, що ви зробили, це трохи прояснить справи.
Phonon

Додано дещо, ось загальне відчуття коду ..
Майкл М

1
Моє запитання було б: що ви очікуєте побачити в даних? Ви не знатимете, чи є у вас хороший підхід, якщо ви не знаєте чогось про базовий сигнал, який ви очікуєте побачити після фільтрації. Крім того, код, який ви показали, є заплутаним. Хоча ви не показуєте ініціалізацію fzмасиву, але здається, що замість цього ви застосовуєте фільтр високої частоти.
Джейсон R

Відповіді:


13

Як вказував @JohnRobertson у " Мішку хитрощів" для позначення сигналів, зберігаючи різкі переходи , тотальний варіатор (TV) позначає ще одну хорошу альтернативу, якщо ваш сигнал є штучною постійною. Це може стосуватися даних акселерометра, якщо ваш сигнал постійно змінюється в різних плато.

Нижче - код Matlab, який виконує позначення телевізора в такому сигналі. Код ґрунтується на документі Доповнений метод Лагрангія для повного відтворення відео . Параметри та повинні бути відрегульовані відповідно до рівня шуму та характеристик сигналу.μρ

Якщо - шумний сигнал, а - сигнал, який оцінюється, функція, яку потрібно мінімізувати, - , де - оператор кінцевих різниць.yxμxy2+Dx1D

function denoise()

f = [-1*ones(1000,1);3*ones(100,1);1*ones(500,1);-2*ones(800,1);0*ones(900,1)];
plot(f);
axis([1 length(f) -4 4]);
title('Original');
g = f + .25*randn(length(f),1);
figure;
plot(g,'r');
title('Noisy');
axis([1 length(f) -4 4]);
fc = denoisetv(g,.5);
figure;
plot(fc,'g');
title('De-noised');
axis([1 length(f) -4 4]);

function f = denoisetv(g,mu)
I = length(g);
u = zeros(I,1);
y = zeros(I,1);
rho = 10;

eigD = abs(fftn([-1;1],[I 1])).^2;
for k=1:100
    f = real(ifft(fft(mu*g+rho*Dt(u)-Dt(y))./(mu+rho*eigD)));
    v = D(f)+(1/rho)*y;
    u = max(abs(v)-1/rho,0).*sign(v);
    y = y - rho*(u-D(f));
end

function y = D(x)
y = [diff(x);x(1)-x(end)];

function y = Dt(x)
y = [x(end)-x(1);-diff(x)];

Результати:

введіть тут опис зображення введіть тут опис зображення введіть тут опис зображення


Дійсно подобається ця відповідь, я буду продовжувати і спробувати. Вибачте, що мені знадобилося так довго, щоб відповісти!
Майкл М

Відмінна відповідь. Дякуємо за деталі. Я шукаю С-версію цього коду. Хтось тут переніс цей код Matlab на C, яким вони хотіли б поділитися? Спасибі.
Рене Лімбергер

Що означає штучна константа?
тилапримера

6

Проблема полягає в тому, що ваш шум має плоский спектр. Якщо припустити білий гауссовий шум (що виявляється хорошим припущенням), його щільність спектру потужності є постійною. Грубо кажучи, це означає, що ваш шум містить усі частоти. Ось чому будь-який частотний підхід, наприклад, DFT або низькочастотні фільтри, не є хорошим. Якими будуть ваші відсічні частоти, оскільки ваш шум по всьому спектру?

Однією з відповідей на це питання є фільтр Вінера, який вимагає знання статистики вашого шуму та потрібного вам сигналу. В основному, шумний сигнал (сигнал + шум) послаблений на частотах, де очікується, що шум буде тертшим, ніж ваш сигнал, і посилюється там, де очікується, що ваш сигнал буде теплішим, ніж ваш шум.

Однак я б запропонував більш сучасні підходи, які використовують нелінійну обробку, наприклад, позначення вейвлетів. Ці методи дають чудові результати. В основному шумний сигнал спочатку розкладається на вейвлети, а потім малі коефіцієнти нульові. Такий підхід працює (а DFT не робить) через багатороздільну здатність вейвлетів. Тобто сигнал обробляється окремо в смугах частот, визначених вейвлет-перетворенням.

У MATLAB введіть "хвильове меню", а потім "SWT, що позначає 1-D". Потім "Файл", "Приклад аналізу", "Шумні сигнали", "з Хааром на рівні 5, Шумні блоки". У цьому прикладі використовується вейвлет Хаар, який повинен добре працювати з вашою проблемою.

Мені не дуже добре в Python, але я вважаю, що ви можете знайти кілька пакетів NumPy, які виконують позначення вейвлетів Haar.


1
Я не погоджуюся з вашим першим твердженням. Ви припускаєте, що інтересний сигнал охоплює повну пропускну здатність вхідної послідовності, що малоймовірно. Ще можна отримати покращене співвідношення сигнал / шум, використовуючи в цьому випадку лінійну фільтрацію, виключаючи позазонний шум. Якщо сигнал сильно зразковий, то при такому простому підході ви можете досягти значного покращення.
Джейсон R

Це правда, і це досягається фільтром Вінера, коли ви знаєте статистику вашого сигналу і свій шум.
Даніель Р. Піпа

Хоча теорія позначення вейвлетів є складною, реалізація настільки ж проста, як описаний вами підхід. Він включає лише банки фільтрів та встановлення порогів.
Даніель Р. Піпа

1
Я зараз досліджую це, опублікую мій прогрес вище, дякую вам і Фонону за всю вашу допомогу поки що!
Майкл М

@DanielPipa У мене немає доступу до відповідних пакунків matlab. Чи можете ви надати паперову чи іншу посилання, що описує метод, який відповідає вашому коду matlab.
Джон Робертсон

0

За пропозицією Даніеля Піпи, я подивився на позначення вейвлетів і знайшов цю чудову статтю Франсіско Бланко-Сільви.

Тут я змінив його код Python для обробки зображень для роботи з 2D (акселерометром), а не з даними 3D (зображення).

Зауважте , поріг "складений" для м'якого порогу на прикладі Франциско. Розгляньте це та змініть для своєї програми.

def wavelet_denoise(data, wavelet, noise_sigma):
    '''Filter accelerometer data using wavelet denoising

    Modification of F. Blanco-Silva's code at: https://goo.gl/gOQwy5
    '''
    import numpy
    import scipy
    import pywt

    wavelet = pywt.Wavelet(wavelet)
    levels  = min(15, (numpy.floor(numpy.log2(data.shape[0]))).astype(int))

    # Francisco's code used wavedec2 for image data
    wavelet_coeffs = pywt.wavedec(data, wavelet, level=levels)
    threshold = noise_sigma*numpy.sqrt(2*numpy.log2(data.size))

    new_wavelet_coeffs = map(lambda x: pywt.threshold(x, threshold, mode='soft'),
                             wavelet_coeffs)

    return pywt.waverec(list(new_wavelet_coeffs), wavelet)

Де:

  • wavelet- ім'я рядка форми вейвлет, яку слід використовувати (див. pywt.wavelist(), наприклад, 'haar')
  • noise_sigma - стандартне відхилення шуму від даних
  • data - масив значень для фільтрації (наприклад, дані осі x, y або z)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.