如何使用java实现低通滤波器

2022-09-01 09:27:11

我正在尝试在Java中实现一个低通滤波器。我的要求很简单,我必须消除超过特定频率的信号(单维)。看起来巴特沃斯过滤器会满足我的需求。

现在重要的是CPU时间应该尽可能低。过滤器必须处理近一百万个样品,我们的用户不喜欢等待太久。是否有任何现成的巴特沃斯滤波器实现具有最佳的过滤算法。


答案 1

我有一个页面描述了一个非常简单,非常低CPU的低通滤波器,它也能够与帧速率无关。我用它来平滑用户输入,也经常用它来绘制帧速率。

http://phrogz.net/js/framerate-independent-low-pass-filter.html

简而言之,在更新循环中:

// If you have a fixed frame rate
smoothedValue += (newValue - smoothedValue) / smoothing

// If you have a varying frame rate
smoothedValue += timeSinceLastUpdate * (newValue - smoothedValue) / smoothing

的值会导致不发生平滑,而较高的值会逐渐平滑结果。smoothing1

该页面有几个用JavaScript编写的函数,但公式与语言无关。


答案 2

这是一个低通滤波器,它在apache数学库中使用傅里叶变换。

    public double[] fourierLowPassFilter(double[] data, double lowPass, double frequency){
    //data: input data, must be spaced equally in time.
    //lowPass: The cutoff frequency at which 
    //frequency: The frequency of the input data.

    //The apache Fft (Fast Fourier Transform) accepts arrays that are powers of 2.
    int minPowerOf2 = 1;
    while(minPowerOf2 < data.length)
        minPowerOf2 = 2 * minPowerOf2;

    //pad with zeros
    double[] padded = new double[minPowerOf2];
    for(int i = 0; i < data.length; i++)
        padded[i] = data[i];


    FastFourierTransformer transformer = new FastFourierTransformer(DftNormalization.STANDARD);
    Complex[] fourierTransform = transformer.transform(padded, TransformType.FORWARD);

    //build the frequency domain array
    double[] frequencyDomain = new double[fourierTransform.length];
    for(int i = 0; i < frequencyDomain.length; i++)
        frequencyDomain[i] = frequency * i / (double)fourierTransform.length;

    //build the classifier array, 2s are kept and 0s do not pass the filter
    double[] keepPoints = new double[frequencyDomain.length];
    keepPoints[0] = 1; 
    for(int i = 1; i < frequencyDomain.length; i++){
        if(frequencyDomain[i] < lowPass)
            keepPoints[i] = 2;
        else
            keepPoints[i] = 0;
    }

    //filter the fft
    for(int i = 0; i < fourierTransform.length; i++)
        fourierTransform[i] = fourierTransform[i].multiply((double)keepPoints[i]);

    //invert back to time domain
    Complex[] reverseFourier = transformer.transform(fourierTransform, TransformType.INVERSE);

    //get the real part of the reverse 
    double[] result = new double[data.length];
    for(int i = 0; i< result.length; i++){
        result[i] = reverseFourier[i].getReal();
    }

    return result;
}

推荐