![]() |
TurboWavelets.Net
Compact C# Implementation for very fast and flexible wavelet transformations
|
00001 // 00002 // Biorthogonal53Wavelet2D.cs 00003 // 00004 // Author: 00005 // Stefan Moebius 00006 // Date: 00007 // 2016-04-17 00008 // 00009 // Copyright (c) 2016 Stefan Moebius 00010 // 00011 // Permission is hereby granted, free of charge, to any person obtaining a copy 00012 // of this software and associated documentation files (the "Software"), to deal 00013 // in the Software without restriction, including without limitation the rights 00014 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00015 // copies of the Software, and to permit persons to whom the Software is 00016 // furnished to do so, subject to the following conditions: 00017 // 00018 // The above copyright notice and this permission notice shall be included in 00019 // all copies or substantial portions of the Software. 00020 // 00021 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00022 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00023 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00024 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00025 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00026 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00027 // THE SOFTWARE. 00028 00029 namespace TurboWavelets 00030 { 00034 public class Biorthogonal53Wavelet2D : Wavelet2D 00035 { 00039 protected const int AllowedMinSize = 3; 00043 protected const float Scale = 2.0f; 00047 protected const float InvScale = 0.5f; 00051 protected const float Mean = 0.5f; 00055 protected const float InvMean = 2.0f; 00059 protected const float Smooth = 0.25f; 00063 protected const float InvSmooth = 4.0f; 00064 00072 public Biorthogonal53Wavelet2D (int width, int height) 00073 : base(AllowedMinSize, AllowedMinSize, width, height) 00074 { 00075 } 00076 00083 public Biorthogonal53Wavelet2D (int width, int height, int minSize) 00084 : base(minSize, AllowedMinSize, width, height) 00085 { 00086 } 00087 00088 #pragma warning disable 1591 // do not show compiler warnings of the missing descriptions 00089 override protected void TransformRow (float[,] src, float[,] dst, int y, int length) 00090 { 00091 if (length >= AllowedMinSize) { 00092 int half = length >> 1; 00093 //if the length is even then subtract 1 from "half" 00094 //as there is the same number of low and high-pass values 00095 //(Note that "numLFValues" is equal to "half+1") 00096 //For a odd length there is one additional quency value (so do not subtract 1) 00097 //"half" is one less than "numLFValues" as we cannot directly 00098 //calculate the last value in the for-loop (array bounds) 00099 if ((length & 1) == 0) 00100 half--; 00101 int offSrc = 0; 00102 // starting offset for high-pass values (= number of low-pass values) 00103 int offdst = half + 1; 00104 int numLFValues = offdst; 00105 00106 float lastHF = 0.0f; 00107 for (int i = 0; i < half; i++) { 00108 //calculate the high-pass value by 00109 //subtracting the mean of the immediate neighbors for every second value 00110 float hf = src [offSrc + 1, y] - (src [offSrc, y] + src [offSrc + 2, y]) * Mean; 00111 //smoothing the low-pass value, scale by factor 2 00112 //(instead of scaling low frequencies by factor sqrt(2) and 00113 //shrinking high frequencies by factor sqrt(2) 00114 //and reposition to have all low frequencies on the left side 00115 dst [i, y] = (src [offSrc, y] + (lastHF + hf) * Smooth) * Scale; 00116 dst [offdst++, y] = hf; 00117 lastHF = hf; 00118 offSrc += 2; 00119 } 00120 if ((length & 1) == 0) { 00121 //the secound last value in the array is our last low-pass value 00122 dst [numLFValues - 1, y] = Scale * src [length - 2, y]; 00123 //the last value is a high-pass value 00124 //however here we just subtract the previos value (so not really a 00125 //biorthogonal 5/3 transformation) 00126 //This is done because the 5/3 wavelet cannot be calculated at the boundary 00127 dst [length - 1, y] = src [length - 1, y] - src [length - 2, y]; 00128 } else { 00129 dst [numLFValues - 1, y] = Scale * src [length - 1, y]; 00130 } 00131 } else { 00132 //We cannot perform the biorthogonal 5/3 wavelet transformation 00133 //for lengths smaller than 3. We could do a simpler transformation... 00134 //Here however, we just copy the values from the source to the destination array 00135 for (int i = 0; i < length; i++) 00136 dst [i, y] = src [i, y]; 00137 } 00138 00139 } 00140 00141 override protected void TransformCol (float[,] src, float[,] dst, int x, int length) 00142 { 00143 if (length >= AllowedMinSize) { 00144 int half = length >> 1; 00145 //if the length is even then subtract 1 from "half" 00146 //as there is the same number of low and high-pass values 00147 //(Note that "numLFValues" is equal to "half+1") 00148 //For a odd length there is one additional low-pass value (so do not subtract 1) 00149 //"half" is one less than "numLFValues" as we cannot directly 00150 //calculate the last value in the for-loop (array bounds) 00151 if ((length & 1) == 0) 00152 half--; 00153 int offSrc = 0; 00154 // starting offset for high-pass values (= number of low-pass values) 00155 int offdst = half + 1; 00156 int numLFValues = offdst; 00157 00158 float lastHF = 0.0f; 00159 for (int i = 0; i < half; i++) { 00160 //calculate the high-pass value by 00161 //subtracting the mean of the immediate neighbors for every second value 00162 float hf = src [x, offSrc + 1] - (src [x, offSrc] + src [x, offSrc + 2]) * Mean; 00163 //smoothing the low-pass value, scale by factor 2 00164 //(instead of scaling low frequencies by factor sqrt(2) and 00165 //shrinking high frequencies by factor sqrt(2) 00166 //and reposition to have all low frequencies on the left side 00167 dst [x, i] = (src [x, offSrc] + (lastHF + hf) * Smooth) * Scale; 00168 dst [x, offdst++] = hf; 00169 lastHF = hf; 00170 offSrc += 2; 00171 } 00172 if ((length & 1) == 0) { 00173 //the secound last value in the array is our last low-pass value 00174 dst [x, numLFValues - 1] = src [x, length - 2] * Scale; 00175 //the last value is a high-pass value 00176 //however here we just subtract the previos value (so not really a 00177 //biorthogonal 5/3 transformation) 00178 //This is done because the 5/3 wavelet cannot be calculated at the boundary 00179 dst [x, length - 1] = src [x, length - 1] - src [x, length - 2]; 00180 } else { 00181 dst [x, numLFValues - 1] = src [x, length - 1] * Scale; 00182 } 00183 } else { 00184 //We cannot perform the biorthogonal 5/3 wavelet transformation 00185 //for lengths smaller than 3. We could do a simpler transformation... 00186 //Here however, we just copy the values from the source to the destination array 00187 for (int i = 0; i < length; i++) 00188 dst [x, i] = src [x, i]; 00189 } 00190 } 00191 00192 override protected void InvTransformRow (float[,] src, float[,] dst, int y, int length) 00193 { 00194 if (length >= AllowedMinSize) { 00195 int half = length >> 1; 00196 //if the length is even then subtract 1 from "half" 00197 //as there is the same number of low and high-pass values 00198 //(Note that "numLFValues" is equal to "half+1") 00199 //For a odd length there is one additional low-pass value (so do not subtract 1) 00200 //"half" is one less than "numLFValues" as we cannot directly 00201 //calculate the last value in the for-loop (array bounds) 00202 if ((length & 1) == 0) 00203 half--; 00204 // number of low-pass values 00205 int numLFValues = half + 1; 00206 00207 float lastLF = InvScale * src [0, y] - src [numLFValues, y] * Smooth; 00208 float lastHF = src [numLFValues, y]; 00209 //Calculate the first two values outside the for loop (array bounds) 00210 dst [0, y] = lastLF; 00211 dst [1, y] = lastHF + lastLF * InvScale; 00212 for (int i = 1; i < half; i++) { 00213 float hf = src [numLFValues + i, y]; 00214 float lf = InvScale * src [i, y]; 00215 //reconstruct the original value by removing the "smoothing" 00216 float lfReconst = lf - (hf + lastHF) * Smooth; 00217 dst [2 * i, y] = lfReconst; 00218 //add reconstructed low-pass value (left side) and high-pass value 00219 dst [2 * i + 1, y] = lfReconst * Mean + hf; 00220 //add other low-pass value (right side) 00221 //This must be done one iteration later, as the 00222 //reconstructed values is not known earlier 00223 dst [2 * i - 1, y] += lfReconst * Mean; 00224 lastHF = hf; 00225 lastLF = lfReconst; 00226 } 00227 00228 if ((length & 1) == 0) { 00229 //restore the last 3 values outside the for loop 00230 //adding the missing low-pass value (right side) 00231 dst [length - 3, y] += src [numLFValues - 1, y] * Mean * InvScale; 00232 //copy the last low-pass value 00233 dst [length - 2, y] = src [numLFValues - 1, y] * InvScale; 00234 //restore the last value by adding last low-pass value 00235 dst [length - 1, y] = src [length - 1, y] + src [numLFValues - 1, y] * InvScale; 00236 } else { 00237 //restore the last 2 values outside the for loop 00238 //adding the missing low-pass value (right side) 00239 dst [length - 2, y] += src [numLFValues - 1, y] * Mean * InvScale; 00240 //copy the last low-pass value 00241 dst [length - 1, y] = src [numLFValues - 1, y] * InvScale; 00242 } 00243 } else { 00244 //We cannot perform the biorthogonal 5/3 wavelet transformation 00245 //for lengths smaller than 3. We could do a simpler transformation... 00246 //Here however, we just copy the values from the source to the destination array 00247 for (int i = 0; i < length; i++) 00248 dst [i, y] = src [i, y]; 00249 } 00250 } 00251 00252 override protected void InvTransformCol (float[,] src, float[,] dst, int x, int length) 00253 { 00254 if (length >= AllowedMinSize) { 00255 int half = length >> 1; 00256 //if the length is even then subtract 1 from "half" 00257 //as there is the same number of low and high-pass values 00258 //(Note that "numLFValues" is equal to "half+1") 00259 //For a odd length there is one additional low-pass value (so do not subtract 1) 00260 //"half" is one less than "numLFValues" as we cannot directly 00261 //calculate the last value in the for-loop (array bounds) 00262 if ((length & 1) == 0) 00263 half--; 00264 // number of low-pass values 00265 int numLFValues = half + 1; 00266 00267 float lastLF = InvScale * src [x, 0] - src [x, numLFValues] * Smooth; 00268 float lastHF = src [x, numLFValues]; 00269 //Calculate the first two values outside the for loop (array bounds) 00270 dst [x, 0] = lastLF; 00271 dst [x, 1] = lastHF + lastLF * InvScale; 00272 for (int i = 1; i < half; i++) { 00273 float hf = src [x, numLFValues + i]; 00274 float lf = InvScale * src [x, i]; 00275 //reconstruct the original value by removing the "smoothing" 00276 float lfReconst = lf - (hf + lastHF) * Smooth; 00277 dst [x, 2 * i] = lfReconst; 00278 //add reconstructed low-pass value (left side) and high-pass value 00279 dst [x, 2 * i + 1] = lfReconst * Mean + hf; 00280 //add other low-pass value (right side) 00281 //This must be done one iteration later, as the 00282 //reconstructed values is not known earlier 00283 dst [x, 2 * i - 1] += lfReconst * Mean; 00284 lastHF = hf; 00285 lastLF = lfReconst; 00286 } 00287 00288 if ((length & 1) == 0) { 00289 //restore the last 3 values outside the for loop 00290 //adding the missing low-pass value (right side) 00291 dst [x, length - 3] += src [x, numLFValues - 1] * Mean * InvScale; 00292 //copy the last low-pass value 00293 dst [x, length - 2] = src [x, numLFValues - 1] * InvScale; 00294 //restore the last value by adding last low-pass value 00295 dst [x, length - 1] = src [x, length - 1] + src [x, numLFValues - 1] * InvScale; 00296 } else { 00297 //restore the last 2 values outside the for loop 00298 //adding the missing low-pass value (right side) 00299 dst [x, length - 2] += src [x, numLFValues - 1] * Mean * InvScale; 00300 //copy the last low-pass value 00301 dst [x, length - 1] = src [x, numLFValues - 1] * InvScale; 00302 } 00303 } else { 00304 //We cannot perform the biorthogonal 5/3 wavelet transformation 00305 //for lengths smaller than 3. We could do a simpler transformation... 00306 //Here however, we just copy the values from the source to the destination array 00307 for (int i = 0; i < length; i++) 00308 dst [x, i] = src [x, i]; 00309 } 00310 } 00311 #pragma warning restore 1591 00312 } 00313 }