|
|
The Discreet Wavelet Transform
| |||||||||
| Haar | |
wavelet![]() |
scale![]() |
| Daubechies | |
wavelet![]() |
scale![]() |
Ones you have chosen the wavelet and scaling filters you compute the DWT like this.
for( n = 0; n < N/2; n++ )
{
yh[n] = x[2n+0]*g[3] + x[2n+1]*g[2] + x[2n+2]*g[1] + x[2n+3]*g[0];
yl[n] = x[2n+0]*h[3] + x[2n+1]*h[2] + x[2n+2]*h[1] + x[2n+3]*h[0];
}
N is the length of the input signal. g is the wavelet filter, h the scaling filter, x the input signal and yh the wavelet coefficients and yl the lowpass filtered signal to be used in the next iteration. yh and yl both have half the length of x. Of course, the filters don't have to have lengths of 4, they can have any length you want as long as it is at least 2 values.
The reconstruction can then be made like this.
for( n = 0; n < N/2; n++ )
{
x[2n ] = yl[n-1]*h[1] + yl[n]*h[3] + yh[n-1]*g[1] + yh[n]*g[3];
x[2n+1] = yl[n-1]*h[0] + yl[n]*h[2] + yh[n-1]*g[0] + yh[n]*g[2];
}
yl and yh are the values computed from the DWT. g and h are the exact same filters as in the DWT. If the filters have been chosen properly then x will be reconstructed without any modifications.
Note that the arrays in these examples are not your ordinary arrays. These are circular arrays, which means that the end connects to the start, or in other words indices should be wrapped so that they are always within the bounds of the array. If you don't use circular arrays you will loose some data in the beginning of the signal and will get some errors when reconstructing the signal. This can be solved by padding the signal with zeroes but it is easier to use circular arrays.
To make it easier to understand what is going on, here is an example transform of a signal with length 8. The transform has been written as a matrix multiplication in order to easier show the wrapping of the signal.
[yl0] = [h3 h2 h1 h0 ][x0] [yl1] = [ h3 h2 h1 h0 ][x1] [yl2] = [ h3 h2 h1 h0][x2] [yl3] = [h1 h0 h3 h2][x3] [yh0] = [g3 g2 g1 g0 ][x4] [yh1] = [ g3 g2 g1 g0 ][x5] [yh2] = [ g3 g2 g1 g0][x6] [yh3] = [g1 g0 g3 g2][x7]
To go back we invert the matrix and multiply again.
[x0] = [h3 h1 g3 g1][yl0] [x1] = [h2 h0 g2 g0][yl1] [x2] = [h1 h3 g1 g3 ][yl2] [x3] = [h0 h2 g0 g2 ][yl3] [x4] = [ h1 h3 g1 g3 ][yh0] [x5] = [ h0 h2 g0 g2 ][yh1] [x6] = [ h1 h3 g1 g3][yh2] [x7] = [ h0 h2 g0 g2][yh3]
Note that these examples only show one iteration of the DWT. You should do the transforms recursively on the low-pass filtered values until you only have 1 more value.
Because of the subsampling at each step there will be the exact same amount of data after the transform as before. Commonly this data is stored in a single array with the lowest level of filtered data first, i.e. the data that was computed last comes first. The last half of this array will then contain the highest frequencies in the original signal.
Hopefully you have gotten an understanding of how wavelet transforms work and how they can be implemented. I haven't told you what wavelet transforms are good for, but I'm sure you have heard at least something about them. The most commonly uses are data compression and signal processing. A simple compression scheme would be to transform the signal and then run-length encode the zeroes. In a scheme like this the wavelet should be chosen to give the most zeroes.
If you have some questions or comments about the article you are welcome to e-mail me about them. Also, don't forget to check out the demo with source code that you can download from my site.
The Wavelet Tutorial, by Robi Polikar
Wavelet Theory, pdf document from the site of Czech Technical University in Prague