Bộ lọc làm mịn Savitzky-Golay cho dữ liệu không cách đều nhau


16

Tôi có một tín hiệu được đo ở tần số 100Hz và tôi cần áp dụng bộ lọc làm mịn Savitzky-Golay cho tín hiệu này. Tuy nhiên, khi kiểm tra kỹ hơn, tín hiệu của tôi không được đo ở tốc độ không đổi hoàn toàn, đồng bằng giữa các lần đo nằm trong khoảng 9,7 đến 10,3 ms.

Có cách nào để sử dụng bộ lọc Savitzky-Golay trên dữ liệu không cách đều nhau không? Có những phương pháp khác mà tôi có thể áp dụng?


Một bài báo năm 1991 của Gilty có khá nhiều chủ đề chính xác này datapdf.com/ . Nhưng tldr, câu trả lời của datageist là ý chính chính (bình phương nhỏ nhất cục bộ). Điều mà Gdvisor quan sát là các hệ số chỉ phụ thuộc vào các biến độc lập và là tuyến tính trong các biến phụ thuộc (như Savitzky-Golay). Sau đó, anh ta đưa ra một cách để tính toán chúng, nhưng nếu bạn không viết một thư viện được tối ưu hóa, bất kỳ bộ lọc hình vuông nhỏ nhất nào cũng có thể được sử dụng.
Dave Pritchard

Câu trả lời:


5

Một phương pháp sẽ là lấy mẫu lại dữ liệu của bạn sao cho nó cách đều nhau, sau đó bạn có thể thực hiện bất kỳ xử lý nào bạn muốn. Lấy mẫu lại được phân tách bằng cách sử dụng bộ lọc tuyến tính sẽ không phải là một lựa chọn tốt vì dữ liệu không cách đều nhau, do đó bạn có thể sử dụng một số loại nội suy đa thức cục bộ (ví dụ: spline khối) để ước tính giá trị của tín hiệu cơ bản là "chính xác" Khoảng thời gian 10 mili giây.


Tôi đã có giải pháp này trong tâm trí như là phương sách cuối cùng. Tôi tự hỏi liệu cuối cùng phương pháp này có đưa ra một giải pháp tốt hơn là chỉ cho rằng tín hiệu của tôi được đo ở tốc độ không đổi.
VLC

Tôi nghĩ ngay cả khi nó được lấy mẫu không đồng đều, bạn vẫn có thể sử dụng phép nội suy chân () (hoặc một bộ lọc thông thấp được lấy mẫu cao khác nhau). Điều này có thể cho kết quả tốt hơn so với spline hoặc pchip
Hilmar

1
@Hilmar: Bạn đã đúng. Có một số cách bạn có thể lấy mẫu lại dữ liệu; phép nội suy gần đúng sẽ là phương pháp "lý tưởng" cho việc lấy mẫu theo dải.
Jason R

15

Do cách thức bộ lọc Savitzky-Golay có nguồn gốc (nghĩa là phù hợp với đa thức bình phương nhỏ nhất cục bộ), nên có sự khái quát hóa tự nhiên đối với việc lấy mẫu không hình thành - nó đắt hơn nhiều về mặt tính toán.

Bộ lọc Savitzky-Golay nói chung

Đối với bộ lọc tiêu chuẩn, ý tưởng là khớp một đa thức với một tập hợp mẫu cục bộ [sử dụng bình phương tối thiểu], sau đó thay thế mẫu trung tâm bằng giá trị của đa thức tại chỉ số trung tâm (tức là 0). Điều đó có nghĩa là các hệ số bộ lọc SG tiêu chuẩn có thể được tạo bằng cách đảo ngược ma trận Vandermonde của các chỉ báo mẫu. Ví dụ, để tạo ra một sự phù hợp parabol địa phương trên khắp năm mẫu (với indicies địa phương -2, -1,0,1,2), hệ phương trình thiết kế Một c = y sẽ như sau:y0Giáo dụcy4Mộtc= =y

[-20-21-22-10-11-12000102101112202122][c0c1c2]= =[y0y1y2y3y4].

Ở phía trên, các là hệ số chưa biết của các hình vuông ít nhất đa thức c 0 + c 1 x + c 2 x 2 . Kể từ khi giá trị của đa thức tại x = 0 là chỉ c 0 , tính toán pseudoinverse của ma trận thiết kế (ví dụ: c = ( A T A ) - 1 Một T y ) sẽ mang lại các hệ số bộ lọc SG ở hàng top. Trong trường hợp này, họ sẽc0Giáo dụcc2c0+c1x+c2x2x= =0c0c= =(MộtTMột)-1MộtTy 

[c0c1c2]= =[-3121712-3-7-40475-3-5-35][y0y1y2y3y4].

Lưu ý rằng vì đạo hàm của c 1 + 2 c 2 x , hàng thứ hai của ma trận (đánh giá c 1 ) sẽ là bộ lọc đạo hàm được làm mịn. Lập luận tương tự áp dụng cho các hàng liên tiếp - chúng đưa ra các đạo hàm bậc cao được làm mịn. Lưu ý rằng tôi đã thu nhỏ ma trận bằng 35 để hàng đầu tiên khớp với các hệ số làm mịn được đưa ra trên Wikipedia (ở trên). Các bộ lọc phái sinh khác nhau bởi các yếu tố tỷ lệ khác.c0+c1x+c2x2c1+2c2xc1

Lấy mẫu Nonuniform

Khi các mẫu cách đều nhau, các hệ số bộ lọc là bất biến dịch, do đó, kết quả chỉ là bộ lọc FIR. Đối với các mẫu không dạng, các hệ số sẽ khác nhau dựa trên khoảng cách mẫu cục bộ, do đó, ma trận thiết kế sẽ cần được xây dựng và đảo ngược ở mỗi mẫu. Nếu thời gian mẫu không hình thành là và chúng tôi xây dựng tọa độ cục bộ t n với mỗi thời gian mẫu trung tâm cố định ở mức 0 , nghĩa làxntn0

t-2= =x-2-x0t-1= =x-1-x0t0= =x0-x0t1= =x1-x0t2= =x2-x0

sau đó mỗi ma trận thiết kế sẽ có dạng sau:

Một= =[t-20t-21t-22t-10t-11t-12t00t01t02t10t11t12t20t21t22]= =[1t-2t-221t-1t-121001t1t121t2t22].

Hàng đầu tiên của giả của chấm với các giá trị mẫu cục bộ sẽ mang lại c 0 , giá trị được làm mịn tại mẫu đó.Một c0


âm thanh như nó di chuyển từ O (log (n)) đến O (n ^ 2).
EngrStudent - Phục hồi Monica

Đây là một triển khai của Scala được mô tả bởi datageist trở lên.
Lõi trung bình

1
@Mediumcore Bạn đã không thêm một liên kết đến bài viết gốc của bạn. Ngoài ra, tôi đã xóa nó vì nó không cung cấp câu trả lời cho câu hỏi. Vui lòng cố gắng chỉnh sửa bài đăng của datageist để thêm một liên kết; nó sẽ được kiểm duyệt sau khi xem xét.
Peter K.

4


fNN/2
-

(phái sinh ai?)


±N/2tt
tTôiTôi


1

Tôi phát hiện ra rằng có hai cách để sử dụng thuật toán savitzky-golay trong Matlab. Một lần như một bộ lọc, và một lần là một chức năng làm mịn, nhưng về cơ bản chúng nên làm như vậy.

  1. yy = sgolayfilt (y, k, f): Ở đây, các giá trị y = y (x) được giả sử là cách đều nhau trong x.
  2. yy = smooth (x, y, span, 'sgolay', độ): Ở đây bạn có thể có x làm đầu vào phụ và tham khảo trợ giúp Matlab x không phải cách đều nhau!

0

Nếu có bất kỳ sự giúp đỡ nào, tôi đã thực hiện C thực hiện phương pháp được mô tả bởi datageist. Miễn phí sử dụng có nguy cơ của riêng bạn.

/**
 * @brief smooth_nonuniform
 * Implements the method described in  /signals/1676/savitzky-golay-smoothing-filter-for-not-equally-spaced-data
 * free to use at the user's risk
 * @param n the half size of the smoothing sample, e.g. n=2 for smoothing over 5 points
 * @param the degree of the local polynomial fit, e.g. deg=2 for a parabolic fit
 */
bool smooth_nonuniform(uint deg, uint n, std::vector<double>const &x, std::vector<double> const &y, std::vector<double>&ysm)
{
    if(x.size()!=y.size()) return false; // don't even try
    if(x.size()<=2*n)      return false; // not enough data to start the smoothing process
//    if(2*n+1<=deg+1)       return false; // need at least deg+1 points to make the polynomial

    int m = 2*n+1; // the size of the filter window
    int o = deg+1; // the smoothing order

    std::vector<double> A(m*o);         memset(A.data(),   0, m*o*sizeof(double));
    std::vector<double> tA(m*o);        memset(tA.data(),  0, m*o*sizeof(double));
    std::vector<double> tAA(o*o);       memset(tAA.data(), 0, o*o*sizeof(double));

    std::vector<double> t(m);           memset(t.data(),   0, m*  sizeof(double));
    std::vector<double> c(o);           memset(c.data(),   0, o*  sizeof(double));

    // do not smooth start and end data
    int sz = y.size();
    ysm.resize(sz);           memset(ysm.data(), 0,sz*sizeof(double));
    for(uint i=0; i<n; i++)
    {
        ysm[i]=y[i];
        ysm[sz-i-1] = y[sz-i-1];
    }

    // start smoothing
    for(uint i=n; i<x.size()-n; i++)
    {
        // make A and tA
        for(int j=0; j<m; j++)
        {
            t[j] = x[i+j-n] - x[i];
        }
        for(int j=0; j<m; j++)
        {
            double r = 1.0;
            for(int k=0; k<o; k++)
            {
                A[j*o+k] = r;
                tA[k*m+j] = r;
                r *= t[j];
            }
        }

        // make tA.A
        matMult(tA.data(), A.data(), tAA.data(), o, m, o);

        // make (tA.A)-¹ in place
        if (o==3)
        {
            if(!invert33(tAA.data())) return false;
        }
        else if(o==4)
        {
            if(!invert44(tAA.data())) return false;
        }
        else
        {
            if(!inverseMatrixLapack(o, tAA.data())) return false;
        }

        // make (tA.A)-¹.tA
        matMult(tAA.data(), tA.data(), A.data(), o, o, m); // re-uses memory allocated for matrix A

        // compute the polynomial's value at the center of the sample
        ysm[i] = 0.0;
        for(int j=0; j<m; j++)
        {
            ysm[i] += A[j]*y[i+j-n];
        }
    }

    std::cout << "      x       y       y_smoothed" << std::endl;
    for(uint i=0; i<x.size(); i++) std::cout << "   " << x[i] << "   " << y[i]  << "   "<< ysm[i] << std::endl;

    return true;
}

làm mịn

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.