LiftingSchemeBaseWavelet.java (6560B)
1 package be.tarsos.dsp.wavelet.lift; 2 3 /** 4 * <p> 5 * class LiftingSchemeBaseWavelet: base class for simple Lifting Scheme wavelets 6 * using split, predict, update or update, predict, merge steps. 7 * </p> 8 * 9 * <p> 10 * Simple lifting scheme wavelets consist of three steps, a split/merge step, 11 * predict step and an update step: 12 * </p> 13 * <ul> 14 * <li> 15 * <p> 16 * The split step divides the elements in an array so that the even elements are 17 * in the first half and the odd elements are in the second half. 18 * </p> 19 * </li> 20 * <li> 21 * <p> 22 * The merge step is the inverse of the split step. It takes two regions of an 23 * array, an odd region and an even region and merges them into a new region 24 * where an even element alternates with an odd element. 25 * </p> 26 * </li> 27 * <li> 28 * <p> 29 * The predict step calculates the difference between an odd element and its 30 * predicted value based on the even elements. The difference between the 31 * predicted value and the actual value replaces the odd element. 32 * </p> 33 * </li> 34 * <li> 35 * <p> 36 * The predict step operates on the odd elements. The update step operates on 37 * the even element, replacing them with a difference between the predict value 38 * and the actual odd element. The update step replaces each even element with 39 * an average. The result of the update step becomes the input to the next 40 * recursive step in the wavelet calculation. 41 * </p> 42 * </li> 43 * 44 * </ul> 45 * 46 * <p> 47 * The split and merge methods are shared by all Lifting Scheme wavelet 48 * algorithms. This base class provides the transform and inverse transform 49 * methods (forwardTrans and inverseTrans). The predict and update methods are 50 * abstract and are defined for a particular Lifting Scheme wavelet sub-class. 51 * </p> 52 * 53 * <p> 54 * <b>References:</b> 55 * </p> 56 * 57 * <ul> 58 * <li> 59 * <a href="http://www.bearcave.com/misl/misl_tech/wavelets/lifting/index.html"> 60 * <i>The Wavelet Lifting Scheme</i></a> by Ian Kaplan, www.bearcave.com. This 61 * is the parent web page for this Java source code.</li> 62 * <li> 63 * <i>Ripples in Mathematics: the Discrete Wavelet Transform</i> by Arne Jense 64 * and Anders la Cour-Harbo, Springer, 2001</li> 65 * <li> 66 * <i>Building Your Own Wavelets at Home</i> in <a 67 * href="http://www.multires.caltech.edu/teaching/courses/waveletcourse/"> 68 * Wavelets in Computer Graphics</a></li> 69 * </ul> 70 * 71 * <h4> 72 * Copyright and Use</h4> 73 * 74 * <p> 75 * You may use this source code without limitation and without fee as long as 76 * you include: 77 * </p> 78 * <blockquote> This software was written and is copyrighted by Ian Kaplan, Bear 79 * Products International, www.bearcave.com, 2001. </blockquote> 80 * <p> 81 * This software is provided "as is", without any warrenty or claim as to its 82 * usefulness. Anyone who uses this source code uses it at their own risk. Nor 83 * is any support provided by Ian Kaplan and Bear Products International. 84 * <p> 85 * Please send any bug fixes or suggested source changes to: 86 * 87 * <pre> 88 * iank@bearcave.com 89 * </pre> 90 * 91 * @author Ian Kaplan 92 */ 93 public abstract class LiftingSchemeBaseWavelet { 94 95 /** "enumeration" for forward wavelet transform */ 96 protected final int forward = 1; 97 /** "enumeration" for inverse wavelet transform */ 98 protected final int inverse = 2; 99 100 /** 101 * Split the <i>vec</i> into even and odd elements, where the even elements 102 * are in the first half of the vector and the odd elements are in the 103 * second half. 104 */ 105 protected void split(float[] vec, int N) { 106 107 int start = 1; 108 int end = N - 1; 109 110 while (start < end) { 111 for (int i = start; i < end; i = i + 2) { 112 float tmp = vec[i]; 113 vec[i] = vec[i + 1]; 114 vec[i + 1] = tmp; 115 } 116 start = start + 1; 117 end = end - 1; 118 } 119 } 120 121 /** 122 * Merge the odd elements from the second half of the N element region in 123 * the array with the even elements in the first half of the N element 124 * region. The result will be the combination of the odd and even elements 125 * in a region of length N. 126 */ 127 protected void merge(float[] vec, int N) { 128 int half = N >> 1; 129 int start = half - 1; 130 int end = half; 131 132 while (start > 0) { 133 for (int i = start; i < end; i = i + 2) { 134 float tmp = vec[i]; 135 vec[i] = vec[i + 1]; 136 vec[i + 1] = tmp; 137 } 138 start = start - 1; 139 end = end + 1; 140 } 141 } 142 143 /** 144 * Predict step, to be defined by the subclass 145 * 146 * @param vec 147 * input array 148 * @param N 149 * size of region to act on (from 0..N-1) 150 * @param direction 151 * forward or inverse transform 152 */ 153 protected abstract void predict(float[] vec, int N, int direction); 154 155 /** 156 * Update step, to be defined by the subclass 157 * 158 * @param vec 159 * input array 160 * @param N 161 * size of region to act on (from 0..N-1) 162 * @param direction 163 * forward or inverse transform 164 */ 165 protected abstract void update(float[] vec, int N, int direction); 166 167 /** 168 * <p> 169 * Simple wavelet Lifting Scheme forward transform 170 * </p> 171 * 172 * <p> 173 * forwardTrans is passed an array of doubles. The array size must be a 174 * power of two. Lifting Scheme wavelet transforms are calculated in-place 175 * and the result is returned in the argument array. 176 * </p> 177 * 178 * <p> 179 * The result of forwardTrans is a set of wavelet coefficients ordered by 180 * increasing frequency and an approximate average of the input data set in 181 * vec[0]. The coefficient bands follow this element in powers of two (e.g., 182 * 1, 2, 4, 8...). 183 * </p> 184 * 185 * @param vec 186 * the vector 187 */ 188 public void forwardTrans(float[] vec) { 189 final int N = vec.length; 190 191 for (int n = N; n > 1; n = n >> 1) { 192 split(vec, n); 193 predict(vec, n, forward); 194 update(vec, n, forward); 195 } 196 } // forwardTrans 197 198 /** 199 * <p> 200 * Default two step Lifting Scheme inverse wavelet transform 201 * </p> 202 * 203 * <p> 204 * inverseTrans is passed the result of an ordered wavelet transform, 205 * consisting of an average and a set of wavelet coefficients. The inverse 206 * transform is calculated in-place and the result is returned in the 207 * argument array. 208 * </p> 209 * 210 * @param vec 211 * the vector 212 */ 213 public void inverseTrans(float[] vec) { 214 final int N = vec.length; 215 216 for (int n = 2; n <= N; n = n << 1) { 217 update(vec, n, inverse); 218 predict(vec, n, inverse); 219 merge(vec, n); 220 } 221 } // inverseTrans 222 223 } // LiftingSchemeBaseWavelet