I'm writing an algorithm that analyzes results of discrete Fourier transform (DFT). The algorithm should detect amplitude peaks in predefined ranges of frequencies. This is an example of such a peak:


Vertical red lines are range boundaries (left and right) and range center (middle).

What are the best criteria for determining the absence of this peak in a specified range?

For now I'm using standard deviation and comparing it to some calibration value. But it can be easily confused with some high amplitude noise like this:


  • 1
    $\begingroup$ Can you do averaging of multiple DFT's? $\endgroup$ – Jim Clay Apr 5 '12 at 13:27
  • $\begingroup$ Yes, it's possible. How can I use it? $\endgroup$ – alexey Apr 5 '12 at 15:47

First convolve the FFT sequence in the given range by a fairly wide gaussian window. In case there is only one peak, this will just widen it. In case there are many peaks (as in the second example), this will merge them into a uniform and less spiky mass.

Then you can use one of the following peakedness metrics:

| improve this answer | |
  • $\begingroup$ Thanks for your answer. Are there any code samples or more detailed algorithm explanation for this technique (gaussian window)? $\endgroup$ – alexey Apr 5 '12 at 15:49
  • $\begingroup$ Filtering with a gaussian window- or any filtering at all, for that matter- will not help with the OP's second picture. $\endgroup$ – Jim Clay Apr 11 '12 at 21:45
  • 1
    $\begingroup$ From what I understood, the problem is determining whether a single, sharp peak is present ; vs many individual peaks. In the first example, filtering by a gaussian will widen the peak, and kurtosis will be quite high. In the second example, filtering by a gaussian will merge all peaks into a more or less flat response, and kurtosis will be very low. $\endgroup$ – pichenettes Apr 11 '12 at 22:03

This answer assumes that the signal you are trying to detect is either not changing frequency with time or is changing slowly compared to your DFT window period (number of samples * sample period).

Your problem is that the SNR in your second picture is terrible, which makes it impossible to know with any confidence what is noise and what is a legitimate signal peak. You need to improve the SNR.

One way to do that is by averaging multiple DFT's. You are already doing the most difficult part of the process- sampling the data, DFT'ing it, and calculating the magnitude. All you have to do is do that multiple times and average the results in each bin. So, if you were doing DFT's that are 512 samples long and you did four DFT's, you would calculate the bins for the average DFT by averaging the bins of the four DFT's. So for bin 0, you would average the bin 0 magnitude of all four DFT's, for bin 1 you would average all four bin 1's, etc.

Mathematically it looks like this-

$ X'[k] = \frac{1}{n} \sum_{i=1}^{n} X_i[k] $, for all k where $X'[k]$ is the averaged DFT, and $n$ is the number of DFT's, and $k$ is the bin index.

You should get about 3 dB of SNR improvement each time you double the number of DFT's. Thus, going from 1 to 2 DFT's gets you 3 dB, 2 to 4 gets you another 3, 4 to 8 gets you another 3 dB, etc. Unfortunately, before long you run into diminishing returns. Also, the number of DFT's you can average is constrained by how quickly the signal is changing frequency. Once the "length" of the averaged DFT (sample period * number of samples per DFT * number of DFT's) gets to the point where the signal's peak is changing bins the signal will start to get smeared.

| improve this answer | |

I am a big fan of Canny edge detectors


They have a lot of nice features, are easy to implement and are also easy to parameterise to perform how you want them to.

Basically, convolve your frequncy domain signall with the first order differential of a gaussian to transform your data.

In matlab, this would be as simple as

Y = filtfilt(   diff( gausswin(69) ), 1, x  )

...if x is your input signal.

You may find the output from this process easier to work with, particularly if you are interested in identifying a localised peak in noise. Not only is the output a smoothed version of the input, but large peaks supress surrounding peaks in a way that may improve the contrast between your signal and noise, possibly allowing your classifier to make a more robust descision as to whethere a peak is present or not.

| improve this answer | |
  • $\begingroup$ How is filtering with a gaussian going to help anything? And what does Canny edge detection got to do with this? $\endgroup$ – Jim Clay Apr 11 '12 at 21:46
  • $\begingroup$ I have used the method with pleasing results to detect the presence or absence of pulses in time series before. It may be useful to the OP as another option to consider or combine with the other suggestions. $\endgroup$ – learnvst Apr 11 '12 at 22:10
  • $\begingroup$ @JimClay I believe the motivation for a gaussian filter here is from CV, where it is known as the 'best edge preserving low-pass filter'. In other words, it will give you the optimal smoothing out of noise, while preserving salient features (of your signal). Technically this stems from its support in the T-domain being equal to its support in the F-domain - it has the lowest T-F product. In contrast, the use of a generic low pass filter will 'smudge' out your signal a lot more than if one were to use a gaussian. $\endgroup$ – Spacey Jul 24 '12 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.