作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想用 Highcharts 呈现脉搏波。有了创意数据,图表就可以了 image
但是,当有噪声时,该算法不起作用 image with bad points
所以我决定用傅里叶变换来做。
有没有库可以做DFT?或者我必须自己写。
请告诉我解决这个问题的库名称或方法,以及你是如何得到这个想法的。
非常感谢!
最佳答案
如果你愿意,你可以自己实现它。以下是如何在 ES6 中实现离散傅里叶变换函数的示例:
import ComplexNumber from '../complex-number/ComplexNumber';
const CLOSE_TO_ZERO_THRESHOLD = 1e-10;
/**
* Discrete Fourier Transform (DFT): time to frequencies.
*
* Time complexity: O(N^2)
*
* @param {number[]} inputAmplitudes - Input signal amplitudes over time (complex
* numbers with real parts only).
* @param {number} zeroThreshold - Threshold that is used to convert real and imaginary numbers
* to zero in case if they are smaller then this.
*
* @return {ComplexNumber[]} - Array of complex number. Each of the number represents the frequency
* or signal. All signals together will form input signal over discrete time periods. Each signal's
* complex number has radius (amplitude) and phase (angle) in polar form that describes the signal.
*
* @see https://gist.github.com/anonymous/129d477ddb1c8025c9ac
* @see https://betterexplained.com/articles/an-interactive-guide-to-the-fourier-transform/
*/
export default function dft(inputAmplitudes, zeroThreshold = CLOSE_TO_ZERO_THRESHOLD) {
const N = inputAmplitudes.length;
const signals = [];
// Go through every discrete frequency.
for (let frequency = 0; frequency < N; frequency += 1) {
// Compound signal at current frequency that will ultimately
// take part in forming input amplitudes.
let frequencySignal = new ComplexNumber();
// Go through every discrete point in time.
for (let timer = 0; timer < N; timer += 1) {
const currentAmplitude = inputAmplitudes[timer];
// Calculate rotation angle.
const rotationAngle = -1 * (2 * Math.PI) * frequency * (timer / N);
// Remember that e^ix = cos(x) + i * sin(x);
const dataPointContribution = new ComplexNumber({
re: Math.cos(rotationAngle),
im: Math.sin(rotationAngle),
}).multiply(currentAmplitude);
// Add this data point's contribution.
frequencySignal = frequencySignal.add(dataPointContribution);
}
// Close to zero? You're zero.
if (Math.abs(frequencySignal.re) < zeroThreshold) {
frequencySignal.re = 0;
}
if (Math.abs(frequencySignal.im) < zeroThreshold) {
frequencySignal.im = 0;
}
// Average contribution at this frequency.
// The 1/N factor is usually moved to the reverse transform (going from frequencies
// back to time). This is allowed, though it would be nice to have 1/N in the forward
// transform since it gives the actual sizes for the time spikes.
frequencySignal = frequencySignal.divide(N);
// Add current frequency signal to the list of compound signals.
signals[frequency] = frequencySignal;
}
return signals;
}
这个函数只是直接实现了公式:
该函数非常慢并且具有 O(n^2)
时间复杂度。如果速度确实对你很重要,你可以选择Fast Fourier Transform相反:
更多细节和描述在这里https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fourier-transform
关于javascript - Javascript 中的离散傅里叶变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44343806/
我是一名优秀的程序员,十分优秀!