5

I have a piecewise constant signal shown below. I want to detect the location of step transition (Marked in red).

My current approach:

I am currently implementing the last step of detecting the discontinuities. However, I cannot get the precise location and end with many false detection.

My question:

  1. Is this the correct approach?
  2. If yes, can someone shed some info/ algorithm to use for the last step?
  3. Please suggest an alternate/ better approach.

Thanks

Original, Smoothed, DWT-detailed Coeff at level 1 plots

VP.
  • 1,200
  • 13
  • 20

5 Answers5

4

Convolve your signal with a 1st derivative of a Gaussian to find the step positions, similar to a Canny edge detection in 1-D. You can do that in a multi-scale approach, starting from a "large" sigma (say ~10 pixels) detect local maxima, then to a smaller sigma (~2 pixels) to converge on the right pixels where the steps are.

You can see an implementation of this approach here.

djvg
  • 11,722
  • 5
  • 72
  • 103
bla
  • 25,846
  • 10
  • 70
  • 101
  • The download link does not work on the interestinglink you sent, maybe someone has a copy ? – Xavier Sep 15 '16 at 17:18
  • it was just a link to the original paper : Canny, John. "A computational approach to edge detection." IEEE Transactions on pattern analysis and machine intelligence 6 (1986): 679-698. https://scholar.google.com/scholar?cluster=6445737130860653197&hl=en&as_sdt=0,5 – bla Sep 15 '16 at 22:13
  • 1
    The last link (URL=http://www.cs.unc.edu/~nanowork/cismm/download/edgedetector/) seems to be broken. There might be a newer version of the same material [here](https://cismm.web.unc.edu/resources/tutorials/edge-detector-1d-tutorial/), I'm not sure. – Bill May 15 '21 at 19:23
  • looks like it :) – bla May 18 '21 at 20:54
3

If your function is really piecewise constant, why not use just abs of diff compared to a threshold?

th = 0.1;
x_steps = x(abs(diff(y)) > th)

where x a vector with your x-axis values, y is your y-axis data, and th is a threshold.

Example:

>> x = [2 3 4 5 6 7 8 9];
>> y = [1 1 1 2 2 2 3 3];
>> th = 0.1;
>> x_steps = x(abs(diff(y)) > th)  

x_steps =

     4     7
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • The signal is piecewise constant but the transitions between the steps are not sharp (its linear change as shown in the image). So taking difference between previous and current value doesn't yield expected result. – VP. Oct 31 '13 at 21:05
  • +1 I appreciated the simplicity of the answer, though it may fail with generic non-stepwise random signals and with stepwise signals with ripples across transitions. – AstoundingJB Jan 31 '18 at 15:36
2

Regarding your point 3: (Please suggest an alternate/ better approach)

I suggest to use a Potts "filter". This is a variational approach to get an accurate estimation of your piecewise constant signal (similar to the total variation minimization). It can be interpreted as adaptive median filtering. Given the Potts estimate u, the jump points are the points of non-zero gradient of u, that is, diff(u) ~= 0. (There are free Matlab implementations of the Potts filters on the web) See also http://en.wikipedia.org/wiki/Step_detection

MKS
  • 31
  • 3
1

Total Variation Denoising can produce a piecewise constant signal. Then, as pointed out above, "abs of diff compared to a threshold" returns the position of the transitions. There exist very efficient algorithms for TVDN that process millions of data points within milliseconds:

http://www.gipsa-lab.grenoble-inp.fr/~laurent.condat/download/condat_fast_tv.c

Here's an implementation of a variational approach with python and matlab interface that also uses TVDN:

https://github.com/qubit-ulm/ebs

kpy776
  • 11
  • 1
0

I think, smoothing with a sharper lowpass filter should work better.

Try to use medfilt1() (a median filter) instead, since you have very concrete levels. If you know how long your plateau is, you can take half/quarter of the plateau length for example. Then you would get very sharp edges. The sharp edges should be detectable using a Haar wavelet or even just using simple differentiation.

Jerome
  • 1