PolynomialWavelets.java (8436B)
1 package be.tarsos.dsp.wavelet.lift; 2 3 /** 4 * <p> 5 * Polynomial wavelets 6 * </p> 7 * <p> 8 * This wavelet transform uses a polynomial interpolation wavelet (e.g., the 9 * function used to calculate the differences). A HaarWavelet scaling function 10 * (the calculation of the average for the even points) is used. 11 * </p> 12 * <p> 13 * This wavelet transform uses a two stage version of the lifting scheme. In the 14 * "classic" two stage Lifting Scheme wavelet the predict stage preceeds the 15 * update stage. Also, the algorithm is absolutely symetric, with only the 16 * operators (usually addition and subtraction) interchanged. 17 * </p> 18 * <p> 19 * The problem with the classic Lifting Scheme transform is that it can be 20 * difficult to determine how to calculate the smoothing (scaling) function in 21 * the update phase once the predict stage has altered the odd values. This 22 * version of the wavelet transform calculates the update stage first and then 23 * calculates the predict stage from the modified update values. In this case 24 * the predict stage uses 4-point polynomial interpolation using even values 25 * that result from the update stage. 26 * </p> 27 * 28 * <p> 29 * In this version of the wavelet transform the update stage is no longer 30 * perfectly symetric, since the forward and inverse transform equations differ 31 * by more than an addition or subtraction operator. However, this version of 32 * the transform produces a better result than the HaarWavelet transform 33 * extended with a polynomial interpolation stage. 34 * </p> 35 * 36 * <p> 37 * This algorithm was suggested to me from my reading of Wim Sweldens' tutorial 38 * <i>Building Your Own Wavelets at Home</i>. 39 * </p> 40 * 41 * </p> 42 * 43 * <pre> 44 * <a href="http://www.bearcave.com/misl/misl_tech/wavelets/lifting/index.html"> 45 * http://www.bearcave.com/misl/misl_tech/wavelets/lifting/index.html</a> 46 * </pre> 47 * 48 * <h4> 49 * Copyright and Use</h4> 50 * 51 * <p> 52 * You may use this source code without limitation and without fee as long as 53 * you include: 54 * </p> 55 * <blockquote> This software was written and is copyrighted by Ian Kaplan, Bear 56 * Products International, www.bearcave.com, 2001. </blockquote> 57 * <p> 58 * This software is provided "as is", without any warrenty or claim as to its 59 * usefulness. Anyone who uses this source code uses it at their own risk. Nor 60 * is any support provided by Ian Kaplan and Bear Products International. 61 * <p> 62 * Please send any bug fixes or suggested source changes to: 63 * 64 * <pre> 65 * iank@bearcave.com 66 * </pre> 67 * 68 * @author Ian Kaplan 69 */ 70 public class PolynomialWavelets extends LiftingSchemeBaseWavelet { 71 final static int numPts = 4; 72 private PolynomialInterpolation fourPt; 73 74 /** 75 * PolynomialWavelets class constructor 76 */ 77 public PolynomialWavelets() { 78 fourPt = new PolynomialInterpolation(); 79 } 80 81 /** 82 * <p> 83 * Copy four points or <i>N</i> (which ever is less) data points from 84 * <i>vec</i> into <i>d</i> These points are the "known" points used in the 85 * polynomial interpolation. 86 * </p> 87 * 88 * @param vec 89 * the input data set on which the wavelet is calculated 90 * @param d 91 * an array into which <i>N</i> data points, starting at 92 * <i>start</i> are copied. 93 * @param N 94 * the number of polynomial interpolation points 95 * @param start 96 * the index in <i>vec</i> from which copying starts 97 */ 98 private void fill(float vec[], float d[], int N, int start) { 99 int n = numPts; 100 if (n > N) 101 n = N; 102 int end = start + n; 103 int j = 0; 104 105 for (int i = start; i < end; i++) { 106 d[j] = vec[i]; 107 j++; 108 } 109 } // fill 110 111 /** 112 * <p> 113 * The update stage calculates the forward and inverse HaarWavelet scaling 114 * functions. The forward HaarWavelet scaling function is simply the average 115 * of the even and odd elements. The inverse function is found by simple 116 * algebraic manipulation, solving for the even element given the average 117 * and the odd element. 118 * </p> 119 * <p> 120 * In this version of the wavelet transform the update stage preceeds the 121 * predict stage in the forward transform. In the inverse transform the 122 * predict stage preceeds the update stage, reversing the calculation on the 123 * odd elements. 124 * </p> 125 */ 126 protected void update(float[] vec, int N, int direction) { 127 int half = N >> 1; 128 129 for (int i = 0; i < half; i++) { 130 int j = i + half; 131 // double updateVal = vec[j] / 2.0; 132 133 if (direction == forward) { 134 vec[i] = (vec[i] + vec[j]) / 2; 135 } else if (direction == inverse) { 136 vec[i] = (2 * vec[i]) - vec[j]; 137 } else { 138 System.out.println("update: bad direction value"); 139 } 140 } 141 } 142 143 /** 144 * <p> 145 * Predict an odd point from the even points, using 4-point polynomial 146 * interpolation. 147 * </p> 148 * <p> 149 * The four points used in the polynomial interpolation are the even points. 150 * We pretend that these four points are located at the x-coordinates 151 * 0,1,2,3. The first odd point interpolated will be located between the 152 * first and second even point, at 0.5. The next N-3 points are located at 153 * 1.5 (in the middle of the four points). The last two points are located 154 * at 2.5 and 3.5. For complete documentation see 155 * </p> 156 * 157 * <pre> 158 * <a href="http://www.bearcave.com/misl/misl_tech/wavelets/lifting/index.html"> 159 * http://www.bearcave.com/misl/misl_tech/wavelets/lifting/index.html</a> 160 * </pre> 161 * 162 * <p> 163 * The difference between the predicted (interpolated) value and the actual 164 * odd value replaces the odd value in the forward transform. 165 * </p> 166 * 167 * <p> 168 * As the recursive steps proceed, N will eventually be 4 and then 2. When N 169 * = 4, linear interpolation is used. When N = 2, HaarWavelet interpolation 170 * is used (the prediction for the odd value is that it is equal to the even 171 * value). 172 * </p> 173 * 174 * @param vec 175 * the input data on which the forward or inverse transform is 176 * calculated. 177 * @param N 178 * the area of vec over which the transform is calculated 179 * @param direction 180 * forward or inverse transform 181 */ 182 protected void predict(float[] vec, int N, int direction) { 183 int half = N >> 1; 184 float d[] = new float[numPts]; 185 186 // int k = 42; 187 188 for (int i = 0; i < half; i++) { 189 float predictVal; 190 191 if (i == 0) { 192 if (half == 1) { 193 // e.g., N == 2, and we use HaarWavelet interpolation 194 predictVal = vec[0]; 195 } else { 196 fill(vec, d, N, 0); 197 predictVal = fourPt.interpPoint(0.5f, half, d); 198 } 199 } else if (i == 1) { 200 predictVal = fourPt.interpPoint(1.5f, half, d); 201 } else if (i == half - 2) { 202 predictVal = fourPt.interpPoint(2.5f, half, d); 203 } else if (i == half - 1) { 204 predictVal = fourPt.interpPoint(3.5f, half, d); 205 } else { 206 fill(vec, d, N, i - 1); 207 predictVal = fourPt.interpPoint(1.5f, half, d); 208 } 209 210 int j = i + half; 211 if (direction == forward) { 212 vec[j] = vec[j] - predictVal; 213 } else if (direction == inverse) { 214 vec[j] = vec[j] + predictVal; 215 } else { 216 System.out 217 .println("PolynomialWavelets::predict: bad direction value"); 218 } 219 } 220 } // predict 221 222 /** 223 * <p> 224 * Polynomial wavelet lifting scheme transform. 225 * </p> 226 * <p> 227 * This version of the forwardTrans function overrides the function in the 228 * LiftingSchemeBaseWavelet base class. This function introduces an extra 229 * polynomial interpolation stage at the end of the transform. 230 * </p> 231 */ 232 public void forwardTrans(float[] vec) { 233 final int N = vec.length; 234 235 for (int n = N; n > 1; n = n >> 1) { 236 split(vec, n); 237 update(vec, n, forward); 238 predict(vec, n, forward); 239 } // for 240 } // forwardTrans 241 242 /** 243 * <p> 244 * Polynomial wavelet lifting Scheme inverse transform. 245 * </p> 246 * <p> 247 * This version of the inverseTrans function overrides the function in the 248 * LiftingSchemeBaseWavelet base class. This function introduces an inverse 249 * polynomial interpolation stage at the start of the inverse transform. 250 * </p> 251 */ 252 public void inverseTrans(float[] vec) { 253 final int N = vec.length; 254 255 for (int n = 2; n <= N; n = n << 1) { 256 predict(vec, n, inverse); 257 update(vec, n, inverse); 258 merge(vec, n); 259 } 260 } // inverseTrans 261 262 } // PolynomialWavelets 263