I want to segment the following signal (units are x: [px], y: [a.u.]) and need a good way to do so. I want to achieve the following:
- I am only interested in the two wide "plateaus" with maximum value (e.g. (1) from ~400px to ~800px and (2) from ~1300px to ~1800px).
- Ideally would like the solution to be parameterless.
In the figure the blue line is the original signal and the orange line is the signal filtered by savgol_filter(signal, 51, 1)
.
I have tried Otsu's method, but it is not optimal, because it is intended for separating a foreground from the background. This is not the case here, which is why I had to do the smoothing (which introduces a parameter(!)) to reduce the noise in the side-peaks, so that they do not "leak" into the foreground, when using Otsu.
I have considered using the derivative of the signal, which should be very strong the flanks of the plateaus (see second figure), but here again the noise in the side-plateaus is causing an issue.
So what would be a good way to segment this signal?
Signal to segment:
signal_filtered = savgol_filter(signal, 51, 1)
plt.plot(signal)
plt.plot(signal_filtered)
plt.show()
Differential of signal and smoothed signal:
plt.plot(np.abs(np.diff(signal))), plt.plot(np.abs(np.diff(savgol_filter(signal, 51, 1)))), plt.show()
EDIT:
Signal with single, non-flat plateau: