I have to detect repetitions in a signal, and I am managing to do it by finding peaks and valleys, and cutting the desired pieces. The following figure shows the pattern wanted, shaded areas are the portions of interest:

enter image description here

The problem is: some of the signals that I'm analyzing, instead of starting with a constant zero, show a very smooth decline, as shown in the following figure:

enter image description here

As a consequence, a peak is detected as one of the first values, and the first repetition is detected wrongly. I'm looking for suggestions to avoid it. I have already tried (not sure if correctly):

  • Using derivatives (diff) to detect inclination.
  • Using a robust regression (robustfit) and finding inclination by the coefficients - too slow.

I'm using a MATLAB code created by someone else, modified by me (original can be found here):

function repeticoes = peakdet(v, delta, x)
%PEAKDET Detect peaks in a vector
%        [MAXTAB, MINTAB] = PEAKDET(V, DELTA) finds the local
%        maxima and minima ("peaks") in the vector V.
%        MAXTAB and MINTAB consists of two columns. Column 1
%        contains indices in V, and column 2 the found values.
%        With [MAXTAB, MINTAB] = PEAKDET(V, DELTA, X) the indices
%        in MAXTAB and MINTAB are replaced with the corresponding
%        X-values.
%        A point is considered a maximum peak if it has the maximal
%        value, and was preceded (to the left) by a value lower by
%        DELTA.
% Eli Billauer, 3.4.05 (Explicitly not copyrighted).
% This function is released to the public domain; Any use is allowed.

maxtab = [];
mintab = [];

v = v(:); % Just in case this wasn't a proper vector

if nargin < 3
  x = (1:length(v))';
  x = x(:);
  if length(v)~= length(x)
    error('Input vectors v and x must have same length');

if (length(delta(:)))>1
  error('Input argument DELTA must be a scalar');

if delta <= 0
  error('Input argument DELTA must be positive');

mn = Inf; mx = -Inf;
mnpos = NaN; mxpos = NaN;

lookformax = 1;

for i=1:length(v)-1
  this = v(i);

  if isempty(maxtab)
    if this >= mx, mx = this; mxpos = x(i); end 
    if this >= mx, mx = this; mxpos = x(i); end
    if this < mn, mn = this; mnpos = x(i); end

  if lookformax
    if this < mx-delta
      maxtab = [maxtab ; mxpos mx];
      mn = this; mnpos = x(i);
      lookformax = 0;
    if this > mn+delta
      mintab = [mintab ; mnpos mn];
      mx = this; mxpos = x(i);
      lookformax = 1;
    if size(maxtab, 1) == 0
        inicios = [];
        finais = [];

    elseif size(maxtab,1) >= size(mintab,1)
        inicios = maxtab(1:size(mintab,1),1);
        finais = mintab(:,1);
    elseif size(maxtab,1) < size(mintab,1)
         inicios = maxtab(:,1);
        finais = mintab(1:size(maxtab, 1),1);
        disp('Erro ao reconhecer repeticoes!')

    repeticoes = [inicios finais];


Any suggestions are welcome!


You mentioned that you have tried the signal derivative to catch the declines. What problems have you faced?

It seems that your problem might be addressed with different words: Let $s(t)$ be your signal, and let $u(t)=ds(t)/dt$. You want a detector to indicate when $a\le u(t)\le b$, with $a,b<0$, for at least $T$ seconds.

If this rewrite of the problem is true, the challenge now is to calculate $u(t)$. You can use u=diff(s), as you mentioned if the signal $s(t)$ has no noise, or you need to estimate $u(t)$ using other techniques like these two for instance.

  • $\begingroup$ Well, I did something similar to what you suggested, without the "a" variable, and failed to determine a proper "b". I'll retry to do it with your suggestions and give a feedback. Thanks! $\endgroup$ Dec 30 '16 at 12:36
  • $\begingroup$ It turns out that the derivation did not work by any method because the signal is noisy - I also tried five-point stencil derivation, but most of the output was flat. Besides, I tried to implement the fft method in the link that you provided, but I'm new to fft and signal processing and could not implement any of the suggested methods in the link. I also tried some filtering without any success. $\endgroup$ Dec 30 '16 at 20:21
  • $\begingroup$ I updated the post with the two techniques with some code and a graph. I hope it helps. $\endgroup$ Dec 30 '16 at 22:40
  • $\begingroup$ Wow! Incredible. Thanks a lot. I'll study more to understand the usage of fft. $\endgroup$ Dec 31 '16 at 19:56

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.