# Obtain Envelope

**URL:** https://discourse.julialang.org/t/obtain-envelope/46643
**Category:** Signal and Image Processing
**Tags:** dsp
**Created:** [September 15, 2020, 3:04pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643 "2020-09-15T15:04:40Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![carlomontec](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carlomontec/32/2011_2.png) [@carlomontec](https://discourse.julialang.org/u/carlomontec)
#### Post date: [September 15, 2020, 3:04pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/1 "2020-09-15T15:04:40Z")

</div>

Hello,

is there any function or library to obtain the envelope of a signal ?

Thank you all.

---

<div class="post-metadata">

### Author: ![ElOceanografo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eloceanografo/32/624_2.png) [@ElOceanografo](https://discourse.julialang.org/u/ElOceanografo)
#### Post date: [September 15, 2020, 4:12pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/2 "2020-09-15T16:12:30Z")

</div>

You can do it using a Hilbert transform, like so:

```julia
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)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/5/e/5e7fbb6228b6b9acc114577526df314386d6a509.png)

---

<div class="post-metadata">

### Author: ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)
#### Post date: [September 15, 2020, 5:21pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/3 "2020-09-15T17:21:27Z")

</div>

line 4 should be `env = abs.(hilbert(y))`

---

<div class="post-metadata">

### Author: ![halleysfifthinc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/halleysfifthinc/32/206280_2.png) [@halleysfifthinc](https://discourse.julialang.org/u/halleysfifthinc)
#### Post date: [September 15, 2020, 5:35pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/4 "2020-09-15T17:35:27Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![ElOceanografo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eloceanografo/32/624_2.png) [@ElOceanografo](https://discourse.julialang.org/u/ElOceanografo)
#### Post date: [September 15, 2020, 5:58pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/5 "2020-09-15T17:58:46Z")

</div>

Thanks, updated!

---

<div class="post-metadata">

### Author: ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)
#### Post date: [September 15, 2020, 6:40pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/6 "2020-09-15T18:40:14Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![carlomontec](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carlomontec/32/2011_2.png) [@carlomontec](https://discourse.julialang.org/u/carlomontec)
#### Post date: [September 15, 2020, 7:54pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/7 "2020-09-15T19:54:15Z")

</div>

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:

![](https://global.discourse-cdn.com/julialang/original/3X/6/8/688322fca25f4204f5b86da46520043ea222f61c.png)

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?

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [September 18, 2020, 8:30pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/8 "2020-09-18T20:30:10Z")

</div>

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).

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [September 18, 2020, 8:52pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/9 "2020-09-18T20:52:12Z")

</div>

One example of the Hilbert envelope of a signal which is not periodic, not band-limited and not continuous:

```julia
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)

```

---

<div class="post-metadata">

### Author: ![klaff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/klaff/32/7637_2.png) [@klaff](https://discourse.julialang.org/u/klaff)
#### Post date: [September 18, 2020, 9:18pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/10 "2020-09-18T21:18:34Z")

</div>

> [@rafael.guerra](#):
>
> ```julia
> using DSP, Plots
> x = collect(-20:0.1:27)
> y = [[-1*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.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [September 19, 2020, 10:04am UTC](https://discourse.julialang.org/t/obtain-envelope/46643/11 "2020-09-19T10:04:57Z")

</div>

An alternative approach to compute the envelope from local extremes using the functions **findlocalmaxima()** and **findlocalminima()** available in [Images.jl](https://github.com/JuliaImages/Images.jl) package:

```julia
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])

```

---

<div class="post-metadata">

### Author: ![carlomontec](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carlomontec/32/2011_2.png) [@carlomontec](https://discourse.julialang.org/u/carlomontec)
#### Post date: [November 16, 2020, 4:58pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/12 "2020-11-16T16:58:48Z")

</div>

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!

---

<div class="post-metadata">

### Author: ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)
#### Post date: [November 16, 2020, 6:50pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/13 "2020-11-16T18:50:18Z")

</div>

The local minima/maxima approach suggested by @rafael.guerra seems to work pretty well:  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/0/3/034a0b282ea1641f56b354dd4a8ab754a9070fef.png)

---

<div class="post-metadata">

### Author: ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)
#### Post date: [November 16, 2020, 6:55pm UTC](https://discourse.julialang.org/t/obtain-envelope/46643/14 "2020-11-16T18:55:58Z")

</div>

Do you know the signal’s frequency? If so the standard method is to do digital down conversion.
