如何使用java实现低通滤波器
我正在尝试在Java中实现一个低通滤波器。我的要求很简单,我必须消除超过特定频率的信号(单维)。看起来巴特沃斯过滤器会满足我的需求。
现在重要的是CPU时间应该尽可能低。过滤器必须处理近一百万个样品,我们的用户不喜欢等待太久。是否有任何现成的巴特沃斯滤波器实现具有最佳的过滤算法。
我正在尝试在Java中实现一个低通滤波器。我的要求很简单,我必须消除超过特定频率的信号(单维)。看起来巴特沃斯过滤器会满足我的需求。
现在重要的是CPU时间应该尽可能低。过滤器必须处理近一百万个样品,我们的用户不喜欢等待太久。是否有任何现成的巴特沃斯滤波器实现具有最佳的过滤算法。
我有一个页面描述了一个非常简单,非常低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
的值会导致不发生平滑,而较高的值会逐渐平滑结果。smoothing
1
该页面有几个用JavaScript编写的函数,但公式与语言无关。
这是一个低通滤波器,它在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;
}