Skip to content

Wavelets

Split the low band again and again: fast changes are seen sharply in time, slow ones in frequency, and dropping small coefficients removes noise.

Before this13.5 · 23.1 · 5 more
Chapter 23 · Lesson 2 of 2

First, the picture

Here a signal with three features at three scales, a slow wave, a step and a burst of fast alternation, is split into averages and differences, and the averages are split again and again. Watch where each feature lands: the burst all in the first level, the slow wave in the few averages left at the end.

Split the low band again and again

64 samples: a slow wave, a step at n = 41 and an 8-sample burst at n = 16 to 23; Haar, three levels.

Three features: a slow wave, a step at n = 41, a burst of fast alternation at n = 16 to 23.

level
0
detail energy
not yet
approximation energy
not yet
0.00 / 14.00 s
Describe this picture

Five stacked strips for 64 samples: a slow wave, a step at n=41n=41 and an 8-sample burst at nn = 16 to 23, split by Haar over three levels. The first strip shows x[n]x[n] as stems for samples 0 to 63, from −1 to 1.6. The strips d₁, d₂ and d₃ hold 32, 16 and 8 bars, each as wide as the samples it covers, from −0.8 to 0.8. The bottom strip holds the approximation so far, labelled a₁, then a₂, then a₃: 8 bars from −2.8 to 2.8 at the end. The readouts are the level and the shares of the total energy in the details and in the approximation. There is no control. At level 1 the burst lands in d₁, four coefficients of 0.7105 to 0.7484, and so does the step (−0.6605 at k=20k=20); everything else in d₁ is at most 0.0693. d₁ holds 11.44 % of the energy and the approximation 88.56 %. At level 2 there is no burst left to split: d₂ holds 1.91 %, and its largest coefficient is the step’s, −0.3834. At level 3 d₃ catches the wave where it is steepest (up to 0.5164) and the step, partly offset by the wave (−0.1190), 5.04 % in all. The 8 approximation coefficients keep 81.62 % of the energy, the slow wave and the step’s height. Each level halves the band and the count.

Averages and differences

In Filter banks (23.1) a two-channel bank split a signal into a low band and a high band. It kept every second sample of each, and it still rebuilt the input exactly. On this page I run that bank again on its own low band, and again on the low band of that. The result is the discrete wavelet transform, the DWT.

Let’s start with the simplest pair of filters, 23.1’s Haar pair, (1,1)/2(1,1)/\sqrt2 and (1,−1)/2(1,-1)/\sqrt2. Filter with each, and keep every second output, as in “Keep every M-th sample” of Downsampling and decimation (22.1). Each pair of samples becomes two numbers:

a1[k]=x[2k]+x[2k+1]2,d1[k]=x[2k]−x[2k+1]2.\begin{aligned} a_1[k]&=\frac{x[2k]+x[2k+1]}{\sqrt2},\\ d_1[k]&=\frac{x[2k]-x[2k+1]}{\sqrt2}. \end{aligned}

I call a1[k]a_1[k] an approximation coefficient: the average of the pair, times 2\sqrt2. And d1[k]d_1[k] is a detail coefficient: half the difference of the pair, times 2\sqrt2. The subscript 1 is the level. From NN samples you get N/2N/2 of each, so there are as many numbers as before.

Depending on which outputs you keep, 23.1’s bank gives these numbers, or −d1-d_1, or pairs the samples one place later. I follow PyWavelets, whose wavedec gives exactly these two formulas.

Why divide by 2\sqrt2 and not by 2? Because then the energy of How big is a signal (1.3) is shared out exactly. For one pair of samples pp and qq:

(p+q2)2+(p−q2)2=2p2+2q22=p2+q2.\begin{aligned} \Big(\frac{p+q}{\sqrt2}\Big)^2+\Big(\frac{p-q}{\sqrt2}\Big)^2&=\frac{2p^2+2q^2}{2}\\ &=p^2+q^2. \end{aligned}

The two rows (1,1)/2(1,1)/\sqrt2 and (1,−1)/2(1,-1)/\sqrt2 are orthogonal and have length 1. They are orthonormal, and “Rows that cancel” in The DFT as a matrix (13.5) showed that such rows keep energy.

Now do the same to a1a_1. Its pairs give a2[k]a_2[k] and d2[k]d_2[k], half as many again. Then a2a_2 gives a3a_3 and d3d_3, and so on. Each level keeps its details and splits only the approximation. For three levels the energy adds up like this:

∑nx[n]2=∑ka3[k]2+∑kd3[k]2+∑kd2[k]2+∑kd1[k]2.\begin{aligned} \sum_n x[n]^2&=\sum_k a_3[k]^2+\sum_k d_3[k]^2\\ &\quad+\sum_k d_2[k]^2+\sum_k d_1[k]^2. \end{aligned}

With more levels it is the same: the last approximation plus every level’s details.

What does each level hold? Up to the factor 2\sqrt2, a1a_1 is a 2-point moving average, a gentle low-pass from Simple smoothing filters (18.2). The pair difference is a gentle high-pass. So d1d_1 holds roughly the top half of the band, π/2\pi/2 to π\pi, and a1a_1 the bottom half.

Keeping every second sample stretches a1a_1‘s half band back out to fill 0 to π\pi (22.1). So the next split takes half of that half: d2d_2 holds roughly π/4\pi/4 to π/2\pi/2 of the original band. Then d3d_3 holds π/8\pi/8 to π/4\pi/4, and a3a_3 keeps what is below π/8\pi/8. Haar’s split is gentle, so these edges are soft, as 23.1 found.

Think of zooming out of a city map. The first zoom loses the alleys, the next the streets, and the motorways are left. Each level of the DWT is one zoom: the details are what that zoom lost, and the approximation is the map that is left.

Split the low band again and again

The picture at the top of the page runs three Haar levels on a signal with three features, each at its own scale. There is a slow wave, one period in 64 samples, and a step at n=41n=41, the u[n]u[n] of Impulse, step and ramp (3.1). There is also a burst of fast alternation, 0.5(−1)n0.5(-1)^n, for nn from 16 to 23 and 0 at every other nn:

x[n]=sin⁡(2πn/64)+u[n−41]+0.5(−1)n(16≤n≤23).\begin{aligned} x[n]={}&\sin(2\pi n/64)+u[n-41]\\ &+0.5(-1)^n\quad(16\le n\le23). \end{aligned}

Its 64 samples run from −0.707-0.707 to 1.5001.500, and its energy is ∑x[n]2=23.087\sum x[n]^2=23.087.

Notice the burst: all of its energy is in level 1. It starts at an even sample, so each pair holds +0.5+0.5 and −0.5-0.5 on top of the wave. The average loses it, and the difference gets 1/2=0.70711/\sqrt2=0.7071, plus a little of the wave. The burst’s energy, 8⋅0.25=28\cdot0.25=2, is exactly the 4⋅0.70712=24\cdot0.7071^2=2 that it adds to d1d_1.

So a1a_1 has no burst left in it already: the burst’s pairs cancelled at the first split, which is why the level-2 caption has no burst left to split. The step lands in d1d_1 because one pair, samples 40 and 41, straddles it. That pair’s difference is −1/2=−0.7071-1/\sqrt2=-0.7071, plus +0.0466+0.0466 from the wave, which makes −0.6605-0.6605.

Everywhere else in d1d_1 the wave changes very little from one sample to the next, so its details are at most 0.0693. At coarser levels the halves being compared lie further apart, and the wave has changed more between them. That is why d3d_3 holds more energy than d2d_2: 5.04 % against 1.91 %.

The largest d3d_3 values, −0.5164-0.5164 and 0.51640.5164, sit at k=0k=0 and k=4k=4. Those blocks cover samples 0 to 7 and 32 to 39, where the wave is steepest. The step still shows at every level, because some pair always straddles it: in d2d_2 it gives −0.5-0.5, partly offset by the wave to −0.3834-0.3834.

At level 3 the approximation is only 8 numbers, yet it keeps 81.62 % of the energy. Each a3[k]a_3[k] is 8\sqrt8 times the average of 8 samples. Those 8 averages trace the slow wave and the step’s height, and nothing finer.

Two ways to tile time and frequency

Each coefficient covers some samples and some band. A level-1 coefficient covers 2 samples and the top half of the band. A level-2 coefficient covers 4 samples and the next quarter. Each level down, a coefficient lasts twice as long and its band is half as wide.

Draw each coefficient as a tile, with time across and frequency up. In “Short window or long window” of Spectrograms & the STFT (15.5), one window length set the tile for every frequency at once. The figure puts that grid next to the wavelet tiles, for 16 samples and three levels.

STFTwavelet transformfrequencyfrequencyd₁d₂d₃a₃timetime
Fig. An STFT uses one tile shape everywhere (15.5’s trade, fixed once); a wavelet transform uses short tiles for high frequencies and long ones for low frequencies. Both have as many tiles as samples.

Fast events, like the burst and the step, are made of high frequencies, and a short tile pins them down in time. A slow wave needs a long look before its frequency is clear, and it gets one. Each scale gets a tile to suit it, and this is what multiresolution means.

It suits signals whose fast parts are brief and whose slow parts last, which is common. It does not suit two close tones high in the band, the case 15.5 needed a long window for: there the wavelet tiles are tall.

Smoother wavelets: Daubechies

Nothing ties the tree to the Haar pair. 23.1’s Daubechies pair db2 has four taps, h0[n]h_0[n] = 0.48296, 0.83652, 0.22414 and −0.12941, and the same tree runs with it. Each filter now reaches past the end of the block, so I take the samples past the end from its start again: the block is treated as periodic.

Haar’s details are 0 wherever the signal is constant. db2’s details are 0 on straight lines too, except where the periodic wrap joins the line’s end to its start. A smooth signal looks almost straight over four samples, so it gives even fewer large details.

Take the slow wave alone. Over three levels, Haar puts 4.96 % of its energy in details, and db2 only 0.45 %, about a tenth.

Where does the name come from? Set one detail coefficient to 1 and every other coefficient to 0, and run the synthesis steps back to samples. Out comes one shape, and the deeper its level, the more samples it covers. Haar’s is a block up and then a block down; db2’s is jagged but has no jumps.

As the level grows, that shape settles to one form that is only stretched: the wavelet, a “small wave”. Doing the same with an approximation coefficient gives the scaling function. Every detail coefficient measures how much of one shifted, stretched copy of the wavelet the signal holds.

The maths behind it · orthogonal changes of basis

The DWT is an orthogonal change of basis. Its basis vectors are shifted and stretched copies of one wavelet, plus the coarsest averages. Thresholding, in the next section, keeps only the few basis vectors with large coefficients: a sparse approximation.

Keep the big coefficients, drop the rest

Now add noise of RMS xnoise,rmsx_\text{noise,rms} to a signal, with RMS from “Four everyday sizes” in 1.3. The transform’s rows are orthonormal, so noise that is the same all along the signal spreads evenly over the coefficients. Each of the NN coefficients gets noise of about that same RMS.

A signal made of flat blocks is different. Its details are 0 inside every block, so it puts its energy into a few large coefficients near the edges. Most details then hold noise alone, and small.

So keep every detail larger than a threshold η\eta, set the rest to 0, and rebuild. The approximation coefficients are always kept. This is hard thresholding. To rebuild, run each level backwards:

x[2k]=a1[k]+d1[k]2,x[2k+1]=a1[k]−d1[k]2,\begin{aligned} x[2k]&=\frac{a_1[k]+d_1[k]}{\sqrt2},\\ x[2k+1]&=\frac{a_1[k]-d_1[k]}{\sqrt2}, \end{aligned}

and the same from a2a_2 and d2d_2 back to a1a_1.

How large should η\eta be? Donoho and Johnstone proposed the universal threshold:

η=xnoise,rms2ln⁡N.\eta=x_\text{noise,rms}\sqrt{2\ln N}.

They chose it so that, as NN grows, the chance that any pure-noise coefficient passes it goes to 0. For N=256N=256 and RMS 0.15, 2ln⁡256=3.3302\sqrt{2\ln256}=3.3302, so η=0.4995\eta=0.4995.

The instrument’s signal is a row of blocks: 0, then 1 from n=50n=50, −0.5-0.5 from 90, 0.7 from 150, and 0 again from 205. The noise comes from the site’s seeded generator, drawn at RMS 0.15; this draw of 256 samples happens to measure 0.1366. Its edges are not at multiples of 2, 4 or 8, so the clean signal has 17 nonzero details, not 5.

Keep the big coefficients, drop the rest

A 256-sample block signal plus noise drawn at RMS 0.15 (this draw: 0.137); Haar DWT, 5 levels; details smaller than η set to 0.

η = 0: every coefficient kept, the noisy signal rebuilt exactly: error 0.1366.

threshold η
0.00
details kept
248 of 248
error RMS
0.1366
0.00 / 13.00 s
Describe this picture

Two stacked panels for a 256-sample block signal plus noise drawn at RMS 0.15 (this draw: 0.137), through a 5-level Haar DWT in which details smaller than η are set to 0. The first is the signal for samples 0 to 255, from −1.2 to 1.5: the noisy samples are small faint dots labelled “noisy”, the clean blocks a thin dashed line labelled “clean”, and the rebuilt signal a solid line labelled “rebuilt”. The second shows the detail coefficients, ∣d∣\lvert d\rvert from 0 to 2.6 against coefficient 0 to 247. Levels 1 to 5 sit side by side, separated by thin lines and named under the axis. Each detail is a bar, solid when kept and faint when set to 0, and a dashed level labelled “η” marks the threshold. The readouts are the threshold η, the details kept, such as “16 of 248”, and the error RMS; they and the rebuilt line follow η as it moves. The clip starts at η = 0, every coefficient kept and the noisy signal rebuilt exactly, with error 0.1366. At η = 0.25, 36 details are kept and the error is 0.0886. At η = 0.50, the universal threshold (0.4995), 16 of 248 are kept, the error is 0.0573, and the edges are still sharp. After the clip the dashed η level becomes a handle, and a slider named “Threshold η” runs from 0 to 1.2 in steps of 0.01. At other values the caption reads like “η = 0.75: 12 kept, error 0.0788.”

Watch the error as η\eta rises: 0.1366, then 0.0886, then 0.0573, less than half of where it started. Of the 16 details kept at 0.50, 15 sit where the clean signal has a detail. The other one is pure noise, 0.5076 at level 1, just above the threshold.

For comparison, a centred 8-point moving average, not drawn in the picture, leaves 0.1235 and blurs every edge. The moving average of Simple smoothing filters (18.2) has no such choice. It turns every edge into an 8-sample ramp, as in “A longer average: less noise, more delay”, and near the edges its error reaches 0.82. Thresholding keeps the large edge coefficients whole, so the rebuilt edges stay where they were.

After the clip, drag the threshold line to set η\eta yourself. Now try 1.2. Only 8 details survive, and the error, 0.1392, is worse than the noisy signal’s 0.1366. Too high a threshold removes the signal too: the smaller edges’ coefficients go with the noise.

Which threshold?

The universal threshold is a principled guess, not the best value. On this trace the error is smallest, 0.0477, for η\eta from 0.51 to 0.52, just above it. There the one noise-only coefficient, 0.5076, has gone, and all 15 signal coefficients stay. At 0.53 a signal coefficient, 0.5279, goes too.

On real data the noise RMS is not known. Donoho and Johnstone estimate it from the level-1 details, which hold mostly noise.

Soft thresholding sets the small details to 0 as well, and also shrinks every kept detail towards 0 by η\eta. Its output has no jumps as η\eta changes, and it tends to look smoother. But it shrinks the large edge coefficients too: on this trace, at the universal threshold, its error is 0.1212 against hard thresholding’s 0.0573.

The maths behind it · nonparametric regression

Wavelet shrinkage is a nonparametric regression estimator: it makes no assumption about the signal’s form beyond having few large coefficients. The universal threshold makes the chance that pure noise survives thresholding go to 0 as NN grows. Soft thresholding is the solution of a lasso problem, least squares with an L1 penalty, in the wavelet basis.

Worked example

1. Haar by hand. Take xx = 1, 3, 2, 2. The pairs give a1a_1 = 4/24/\sqrt2, 4/24/\sqrt2 = 2.8284, 2.8284 and d1d_1 = −2/2-2/\sqrt2, 0 = −1.4142-1.4142, 0. One more level gives a2=(2.8284+2.8284)/2=4a_2=(2.8284+2.8284)/\sqrt2=4 and d2=0d_2=0.

The energy checks: 1+9+4+4=181+9+4+4=18, and 42+02+(−1.4142)2+02=16+2=184^2+0^2+(-1.4142)^2+0^2=16+2=18. Going back, x[0]=(2.8284−1.4142)/2=1x[0]=(2.8284-1.4142)/\sqrt2=1 and x[1]=(2.8284+1.4142)/2=3x[1]=(2.8284+1.4142)/\sqrt2=3.

2. The tree. The 64-sample signal has energy 23.087. After three Haar levels, d1d_1 holds 11.44 %, d2d_2 1.91 %, d3d_3 5.04 % and a3a_3 81.62 %. These add to 100 % before rounding; rounded, they make 100.01.

3. Denoising. With N=256N=256 and RMS 0.15, ln⁡256=5.5452\ln256=5.5452, so η=0.1511.0904=0.4995\eta=0.15\sqrt{11.0904}=0.4995. Hard thresholding keeps 16 of the 248 details, and the error falls from 0.1366 to 0.0573.

Where you’ll meet this

JPEG 2000 compresses images with a wavelet transform whose analysis and synthesis filters differ, a biorthogonal pair, which lets both be symmetric. Its two-dimensional version splits rows and columns level by level; Image compression (28.4) comes back to it. The FBI’s fingerprint archive uses a wavelet standard too, WSQ.

Wavelet denoising cleans ECGs and seismic traces, where sharp events sit in slow backgrounds; ECG processing (31.1) uses it. In machine learning, the energies of the levels make multiscale features for classifying signals.

PyWavelets reproduces this page’s wavelet numbers with pywt.wavedec(x, 'haar', mode='periodization'), pywt.threshold and pywt.waverec. For the ideas in depth, see S. Mallat, A Wavelet Tour of Signal Processing (3rd ed., 2009), and G. Strang and T. Nguyen, Wavelets and Filter Banks (1996).

Reference card

QuantityFormulaNotes
Haar levela1[k]=x[2k]+x[2k+1]2a_1[k]=\frac{x[2k]+x[2k+1]}{\sqrt2}, d1[k]=x[2k]−x[2k+1]2d_1[k]=\frac{x[2k]-x[2k+1]}{\sqrt2}then the same on a1a_1
Inverse Haar levelx[2k]=a1[k]+d1[k]2x[2k]=\frac{a_1[k]+d_1[k]}{\sqrt2}, x[2k+1]=a1[k]−d1[k]2x[2k+1]=\frac{a_1[k]-d_1[k]}{\sqrt2}rebuild level by level
DWTsplit the approximation again, level by levelan iterated 23.1 bank
Energy∑x2=∑am2+∑levels∑d2\sum x^2=\sum a_m^2+\sum_{\text{levels}}\sum d^2orthonormal
Hard thresholdkeep ∣d∣>η\lvert d\rvert > \eta, else 0then rebuild
Universal thresholdη=xnoise,rms2ln⁡N\eta=x_\text{noise,rms}\sqrt{2\ln N}Donoho–Johnstone
Tilingshort tiles high, long tiles lowthe STFT’s are all alike

End of lesson 23.2

Where to go next.

Phasorium
LibraryEvery lesson, in order

Parts

About Phasorium
Look