Hello,
is there any function or library to obtain the envelope of a signal ?
Thank you all.
Hello,
is there any function or library to obtain the envelope of a signal ?
Thank you all.
You can do it using a Hilbert transform, like so:
using DSP, Plots
x = 0:0.1:200
y = sin.(x) .+ sin.(1.2x)
env = abs.(hilbert(y))
plot(x, y)
plot!(x, env)
plot!(x, -env)
line 4 should be env = abs.(hilbert(y))
Could you give an example of what your signal source is? Depending on the field, “envelope” is not always a completely defined concept. For example, EMG signals commonly include tall and narrow peaks that would unduly distort an envelope calculated with the Hilbert transform method above. The most common method of obtaining the envelope for EMG signals is to full-wave rectify (ie abs(x)
) and low pass filter.
Thanks, updated!
Crystal radio to the rescue! My tech roots lie in shortwave and ham radio many many years ago and it’s neat when those basics come up in other contexts.
Thank you all for your input!
I work with signals from vibrating structures. Sometimes the signals are smooth and sometimes are non-smooth. They look quite similar to the plot in the link below:
For this kind of signals , I think the approach mentioned by @ElOceanografo seems adequate. Is it apt also for signals non-symmetric respect to the time axis?
I believe that the discrete Hilbert envelope technique used here may assume continuous, band-limited (non-aliased), periodic signals. One may want to taper the beginning and end of the signal to avoid a possible discontinuity there (from the assumed periodicity).
One example of the Hilbert envelope of a signal which is not periodic, not band-limited and not continuous:
using DSP, Plots
x = collect(-20:0.1:27)
y = [[-cos(u) for u in x if u<0]; 2*[cos(u)+cos(1.2u) for u in x if u>=0]];
env = abs.(hilbert(y))
plot(x, y)
plot!(x, env)
plot!(x, -env)
Neat example. If your application lets you ignore those transients (maybe you know a priori where they will be) it does pretty well.
An alternative approach to compute the envelope from local extremes using the functions findlocalmaxima() and findlocalminima() available in Images.jl package:
using Images, Plots
x = collect(-20:0.1:27)
y = [[-cos(u) for u in x if u<0]; 2*[cos(u)+cos(1.2u) for u in x if u>=0]];
maxy_ix = findlocalmaxima(y)
miny_ix = findlocalminima(y)
plot(x, y)
plot!(x[maxy_ix],y[maxy_ix])
plot!(x[miny_ix],y[miny_ix])
Thank you for your valuable contributions. The solution via the Hilbert transform give me unfortunately too much additional high frequency content. I suspect given the non-smoothness of the input signal, although I am quite ignorant in the topic.
Would you recommend a way of filtering it? My goal is to have an estimate of mean, and standard deviation from the peak-to-peak amplitude of the signal. My current best bet is to apply a lowpass filter and then apply the Hilbert transform. So far looks quite good. I admit this is more theory than Julia, nonetheless Im quite thankful. Muchas gracias!
The local minima/maxima approach suggested by @rafael.guerra seems to work pretty well:
Do you know the signal’s frequency? If so the standard method is to do digital down conversion.