# How to detect peaks ignoring soft declivity?

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: 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:

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))';
else
x = x(:);
if length(v)~= length(x)
error('Input vectors v and x must have same length');
end
end

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

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

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
else
if this >= mx, mx = this; mxpos = x(i); end
if this < mn, mn = this; mnpos = x(i); end
end

if lookformax
if this < mx-delta
maxtab = [maxtab ; mxpos mx];
mn = this; mnpos = x(i);
lookformax = 0;
end
else
if this > mn+delta
mintab = [mintab ; mnpos mn];
mx = this; mxpos = x(i);
lookformax = 1;
end
end
end
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);
else
disp('Erro ao reconhecer repeticoes!')
end

repeticoes = [inicios finais];

end


Any suggestions are welcome!

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.