TurboWavelets.Net
Compact C# Implementation for very fast and flexible wavelet transformations
TurboWavelets/Biorthogonal53Wavelet2D.cs
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 }
 All Classes Namespaces Functions Variables Properties