Chọn bộ lọc chính xác cho dữ liệu gia tốc


28

Tôi còn khá mới với DSP và đã thực hiện một số nghiên cứu về các bộ lọc có thể để làm mịn dữ liệu gia tốc trong python. Một ví dụ về loại dữ liệu mà tôi gặp phải có thể được nhìn thấy trong hình ảnh sau đây:

Dữ liệu gia tốc

Về cơ bản, tôi đang tìm kiếm lời khuyên để làm mịn dữ liệu này để cuối cùng chuyển đổi nó thành vận tốc và chuyển vị. Tôi hiểu rằng gia tốc kế từ điện thoại di động cực kỳ ồn ào.

Tôi không nghĩ rằng tôi có thể sử dụng bộ lọc Kalman vào lúc này vì tôi không thể giữ thiết bị để tham chiếu tiếng ồn do dữ liệu tạo ra (Tôi đọc rằng điều cần thiết là đặt thiết bị phẳng và tìm lượng nhiễu từ các lần đọc đó?)

FFT đã tạo ra một số kết quả thú vị. Một trong những nỗ lực của tôi là FFT tín hiệu tăng tốc, sau đó đưa ra các tần số thấp để có giá trị FFT tuyệt đối bằng 0. Sau đó, tôi đã sử dụng omega số học và FFT nghịch đảo để đạt được âm mưu cho vận tốc. Kết quả như sau:

Tín hiệu đã lọc

Đây có phải là một cách tốt để đi về mọi thứ? Tôi đang cố gắng loại bỏ tính chất nhiễu tổng thể của tín hiệu nhưng các đỉnh rõ ràng như trong khoảng 80 giây cần phải được xác định.

Tôi cũng đã mệt mỏi khi sử dụng bộ lọc thông thấp trên dữ liệu gia tốc ban đầu, điều này đã làm rất tốt việc làm mịn nó, nhưng tôi không thực sự chắc chắn sẽ đi đâu từ đây. Bất kỳ hướng dẫn về nơi để đi từ đây sẽ thực sự hữu ích!

EDIT: Một chút mã:

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

Vì vậy, về cơ bản, ive đã thực hiện FFT trên dữ liệu gia tốc của mình, cho Sz, lọc tần số cao ra bằng bộ lọc tường gạch đơn giản (tôi biết nó không lý tưởng). Sau đó, tôi đã sử dụng số học omega trên FFT của dữ liệu. Cũng cảm ơn rất nhiều cho datageist đã thêm hình ảnh của tôi vào bài viết của tôi :)


Chào mừng đến với DSP! Đường cong màu đỏ trong ảnh thứ hai của bạn có phải là phiên bản "được làm mịn" của dữ liệu gốc (màu xanh lá cây) không?
Phonon

Đường cong màu đỏ là (hy vọng!) Một đường cong vận tốc được tạo ra từ fft theo sau là lọc, theo sau là số học omega (chia cho 2 * pi f j), theo sau là inv. fft
Michael M

1
Có lẽ nếu bạn bao gồm một biểu thức toán học hoặc mã giả chính xác hơn cho những gì bạn đã làm sẽ làm mọi thứ rõ ràng hơn một chút.
Phonon

Đã thêm một số bây giờ, đó là cảm nhận chung về mã ..
Michael M

1
Câu hỏi của tôi sẽ là: bạn mong đợi gì trong dữ liệu? Bạn sẽ không biết liệu bạn có cách tiếp cận tốt hay không trừ khi bạn biết điều gì đó về tín hiệu cơ bản mà bạn muốn thấy sau khi lọc. Ngoài ra, mã mà bạn hiển thị là khó hiểu. Mặc dù bạn không hiển thị khởi tạo fzmảng, nhưng có vẻ như bạn đang áp dụng bộ lọc đường cao thay thế.
Jason R

Câu trả lời:


13

Như được chỉ ra bởi @JohnRobertson trong Bag Tricks để khử tín hiệu trong khi duy trì chuyển đổi sắc nét , khử nhiễu Total Variaton (TV) là một lựa chọn tốt khác nếu tín hiệu của bạn là hằng số khôn ngoan. Đây có thể là trường hợp của dữ liệu gia tốc, nếu tín hiệu của bạn thay đổi giữa các cao nguyên khác nhau.

Dưới đây là mã Matlab thực hiện khử nhiễu TV trong tín hiệu như vậy. Mã này dựa trên bài báo Phương pháp Lagrangian tăng cường để khôi phục video biến đổi tổng . Các thông số và phải được điều chỉnh theo mức độ nhiễu và đặc tính tín hiệu.μρ

Nếu là tín hiệu nhiễu và là tín hiệu được ước tính, hàm được thu nhỏ là , trong đó là toán tử sai phân hữu hạn.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)];

Các kết quả:

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây


Thực sự thích câu trả lời này, sẽ tiếp tục và thử nó. Xin lỗi, tôi mất quá nhiều thời gian để trả lời!
Michael M

Câu trả lời tuyệt vời. Cảm ơn các chi tiết. Tôi đang tìm phiên bản C của mã này. Bất cứ ai ở đây đã chuyển mã MATLAB này sang C mà họ muốn chia sẻ? Cảm ơn.
Rene Limberger

Không liên tục mảnh khôn ngoan có nghĩa là gì?
cá rô phi

6

Vấn đề là tiếng ồn của bạn có phổ phẳng. Nếu bạn giả sử nhiễu Gaussian trắng (hóa ra là giả định tốt) thì mật độ phổ công suất của nó là không đổi. Nói một cách đơn giản, điều đó có nghĩa là tiếng ồn của bạn chứa tất cả các tần số. Đó là lý do tại sao bất kỳ cách tiếp cận tần số nào, ví dụ như bộ lọc DFT hoặc bộ lọc thông thấp, không phải là một bộ lọc tốt. Điều gì sẽ là tần số cắt của bạn vì tiếng ồn của bạn là tất cả các phổ?

Một câu trả lời cho câu hỏi này là bộ lọc Wiener, đòi hỏi kiến ​​thức về thống kê tiếng ồn và tín hiệu mong muốn của bạn. Về cơ bản, tín hiệu nhiễu (tín hiệu + nhiễu) bị suy giảm theo tần số mà tiếng ồn được dự kiến ​​là lớn hơn tín hiệu của bạn và nó được khuếch đại trong đó tín hiệu của bạn được dự kiến ​​là lớn hơn nhiễu của bạn.

Tuy nhiên, tôi sẽ đề xuất các phương pháp hiện đại hơn sử dụng xử lý phi tuyến tính, ví dụ như khử nhiễu sóng con. Những phương pháp này cung cấp kết quả tuyệt vời. Về cơ bản, tín hiệu nhiễu đầu tiên được phân tách thành các sóng nhỏ và sau đó các hệ số nhỏ bằng không. Cách tiếp cận này hoạt động (và DFT không) vì tính chất đa độ phân giải của sóng con. Nghĩa là, tín hiệu được xử lý riêng trong các dải tần được xác định bởi biến đổi wavelet.

Trong MATLAB, nhập 'wavemenu' và sau đó 'SWT khử nhiễu 1-D'. Sau đó, 'Tệp', 'Phân tích ví dụ', 'Tín hiệu nhiễu', 'với Haar ở cấp 5, các khối nhiễu'. Ví dụ này sử dụng Haar wavelet, sẽ hoạt động tốt cho vấn đề của bạn.

Tôi không giỏi về Python, nhưng tôi tin rằng bạn có thể tìm thấy một số gói NumPy thực hiện khử nhiễu Haar wavelet.


1
Tôi sẽ không đồng ý với tuyên bố đầu tiên của bạn. Bạn đang giả định rằng tín hiệu quan tâm bao trùm toàn bộ băng thông của chuỗi đầu vào, điều này là không thể. Vẫn có thể đạt được tỷ lệ nhiễu tín hiệu được cải thiện bằng cách sử dụng bộ lọc tuyến tính trong trường hợp này, loại bỏ nhiễu ngoài dải. Nếu tín hiệu quá lớn, thì bạn có thể có được một cải tiến lớn với cách tiếp cận đơn giản như vậy.
Jason R

Đó là sự thật và điều này đạt được nhờ bộ lọc Wiener, khi bạn biết số liệu thống kê về tín hiệu và nhiễu của bạn.
Daniel R. Pipa

Mặc dù lý thuyết đằng sau việc khử nhiễu sóng là phức tạp, nhưng việc thực hiện đơn giản như cách tiếp cận bạn mô tả. Nó chỉ liên quan đến các ngân hàng lọc và ngưỡng.
Daniel R. Pipa

1
Bây giờ tôi đang nghiên cứu về vấn đề này, sẽ đăng tiến trình của tôi ở trên, cảm ơn cả bạn và Phonon vì tất cả sự giúp đỡ của bạn cho đến nay!
Michael M

@DanielPipa Tôi không có quyền truy cập vào các gói MATLAB được đề cập. Bạn có thể cung cấp một bài báo hoặc tài liệu tham khảo khác mô tả phương pháp tương ứng với mã MATLAB của bạn.
John Robertson

0

Theo đề nghị của Daniel Pipa, tôi đã xem qua việc khử nhiễu sóng con và tìm thấy bài viết xuất sắc này của Francisco Blanco-Silva.

Ở đây tôi đã sửa đổi mã Python của mình để xử lý hình ảnh để hoạt động với dữ liệu 2D (gia tốc kế) thay vì dữ liệu 3D (hình ảnh).

Lưu ý , ngưỡng là "tạo nên" cho ngưỡng mềm trong ví dụ của Francisco. Xem xét điều này và sửa đổi cho ứng dụng của bạn.

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)

Ở đâu:

  • wavelet- tên chuỗi của dạng wavelet sẽ được sử dụng (xem pywt.wavelist(), ví dụ 'haar')
  • noise_sigma - độ lệch chuẩn của nhiễu từ dữ liệu
  • data - mảng các giá trị cần lọc (ví dụ: dữ liệu trục x, y hoặc z)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.