/* WL_FswptMatrix * * Computes the full decomposition tree for the symmetric wavelet * transform up to the desired level. */ public static int WL_FswptMatrix(double[,] source, ref double[,] dest, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { int nRows, nCols; double[,] tmp; double[,] tmpDest; if (levels == 0) { Array.Copy(source, dest, rows * cols); return(0); } if (WlcSWavelet.WL_FswtMatrix(source, ref dest, rows, cols, 1, lowpass, hipass) != 0) { return(1); } nRows = rows / 2; nCols = cols / 2; tmpDest = new double[nRows, nCols]; tmp = WaveletUtil.WL_Extract2D(dest, 0, 0, nRows, nCols); if (WL_FswptMatrix(tmp, ref tmpDest, nRows, nCols, levels - 1, lowpass, hipass) != 0) { return(1); } WaveletUtil.WL_Put2D(ref dest, tmpDest, 0, 0, nRows, nCols); /* Horizontal */ tmp = WaveletUtil.WL_Extract2D(dest, 0, nCols, nRows, nCols); if (WL_FswptMatrix(tmp, ref tmpDest, nRows, nCols, levels - 1, lowpass, hipass) != 0) { return(1); } WaveletUtil.WL_Put2D(ref dest, tmpDest, 0, nCols, nRows, nCols); /* Diagonal */ tmp = WaveletUtil.WL_Extract2D(dest, nRows, nCols, nRows, nCols); if (WL_FswptMatrix(tmp, ref tmpDest, nRows, nCols, levels - 1, lowpass, hipass) != 0) { return(1); } WaveletUtil.WL_Put2D(ref dest, tmpDest, nRows, nCols, nRows, nCols); /* Vertical */ tmp = WaveletUtil.WL_Extract2D(dest, nRows, 0, nRows, nCols); if (WL_FswptMatrix(tmp, ref tmpDest, nRows, nCols, levels - 1, lowpass, hipass) != 0) { return(1); } WaveletUtil.WL_Put2D(ref dest, tmpDest, nRows, 0, nRows, nCols); return(0); }
/* WL_FwtVolume * * Perform a LEVELS-deep separable forward wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * ROWS and COLS indicate the size of the SOURCE & DEST volume. * The transformed coefficients in DEST are stored in the Mallat * representation. * * The edge treatment is to perform periodic extension. */ public static int WL_FwtVolume(double[,,] source, ref double[,,] dest, int depth, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { double[] tempSource; double[] tempDest; int d, c, r, level; /* allocate the temp arrays for columns */ tempSource = new double[Math.Max(rows, depth)]; tempDest = new double[Math.Max(rows, depth)]; /* copy the source to dest to facilitate multiple levels */ for (d = 0; d < depth; d++) { for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { dest[d, r, colNum] = source[d, r, colNum]; } } } for (level = 0; level < levels; level++, rows /= 2, cols /= 2, depth /= 2) { /* transform each row */ for (d = 0; d < depth; d++) { for (r = 0; r < rows; r++) { var extract = WaveletUtil.Extract1DArray(dest, d, r, cols); var result = WL_FwtVector(extract, ref extract, cols, 1, lowpass, hipass); WaveletUtil.Patch1DArray(extract, ref dest, d, r, cols); if (result != 0) { return(1); } } } //# ifdef DEBUG_MATRIX // fprintf(stderr, "level %d ROW:\n", level); // for (r = 0; r < rows; r++) // { // for (c = 0; c < cols; c++) fprintf(stderr, "%f ", dest[r][c]); // fprintf(stderr, "\n"); // } //#endif /* transform each column */ for (d = 0; d < depth; d++) { for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[d, r, c]; } if (WL_FwtVector(tempSource, ref tempDest, rows, 1, lowpass, hipass) != 0) { return(1); } for (r = 0; r < rows; r++) { dest[d, r, c] = tempDest[r]; } } } /* transform each depth line */ for (r = 0; r < rows; r++) { for (c = 0; c < cols; c++) { for (d = 0; d < depth; d++) { tempSource[d] = dest[d, r, c]; } if (WL_FwtVector(tempSource, ref tempDest, depth, 1, lowpass, hipass) != 0) { return(1); } for (d = 0; d < depth; d++) { dest[d, r, c] = tempDest[d]; } } } //# ifdef DEBUG_MATRIX // fprintf(stderr, "level %d COL:\n", level); // for (r = 0; r < rows; r++) // { // for (c = 0; c < cols; c++) fprintf(stderr, "%f ", dest[r][c]); // fprintf(stderr, "\n"); // } //#endif } return(0); }
/* WL_IwtVector * * Perform a LEVELS-deep inverse wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. Optional * arguments indicating how edges should be treated are in ARGV. * LENGTH is the length of the SOURCE & DEST vectors. * The coefficients in SOURCE are expected to be in the Mallat format. */ public static int WL_IwtVector(double[] source, ref double[] dest, int length, int levels, WL_Filter lowpass, WL_Filter hipass) { double[] upLow; /* extended upsampled low frequency vector */ double[] upHi; /* extended upsampled high frequency vector */ int i, j, level; int hisize = hipass.Length; int lowsize = lowpass.Length; double[] hicoefs = hipass.Coefs; double[] lowcoefs = lowpass.Coefs; double sum; int left = Math.Max(lowpass.Offset, hipass.Offset); int right = Math.Max(lowpass.Length - lowpass.Offset - 1, hipass.Length - hipass.Offset - 1); // These are "pointers" into arrays int result; int hidata; int lowdata; /* allocate memory for the extended copies of source */ upLow = new double[length + left + right]; upHi = new double[length + left + right]; length = length / WaveletUtil.WL_pow2(levels - 1); /* copy the lowest frequency portion to dest to facilitate multiple levels */ for (i = 0; i < length; i++) { dest[i] = source[i]; } for (level = 0; level < levels; level++, length *= 2) { /* upsample the source data */ for (i = 0, j = left; i < length / 2; i++) { upLow[j] = dest[i]; upHi[j] = source[length / 2 + i]; j += 1; upLow[j] = 0; upHi[j] = 0; j += 1; } j = 0; for (i = length - left; i < length; i++, j++) { upLow[j] = upLow[left + i]; upHi[j] = upHi[left + i]; } for (i = 0; i < length; i++, j++) { upLow[j] = upLow[left + i]; upHi[j] = upHi[left + i]; } for (i = 0; i < right; i++, j++) { upLow[j] = upLow[left + i]; upHi[j] = upHi[left + i]; } //# ifdef DEBUG // fprintf(stderr, "level %d upLow: ", level); // for (i = 0; i < length + left + right; i++) // fprintf(stderr, "%f ", upLow[i]); // fprintf(stderr, "\n"); // fprintf(stderr, "level %d upHi: ", level); // for (i = 0; i < length + left + right; i++) // fprintf(stderr, "%f ", upHi[i]); // fprintf(stderr, "\n"); //#endif lowdata = left - lowpass.Offset; hidata = left - hipass.Offset; result = 0; for (i = 0; i < length; i++, lowdata++, hidata++) { sum = 0; for (j = 0; j < lowsize; j++) { sum += upLow[lowdata + j] * lowcoefs[j]; } for (j = 0; j < hisize; j++) { sum += upHi[hidata + j] * hicoefs[j]; } dest[result++] = sum; } //# ifdef DEBUG // fprintf(stderr, "level %d result: ", level); // for (i = 0; i < length; i++) fprintf(stderr, "%f ", dest[i]); // fprintf(stderr, "\n"); //#endif } return(0); }
/* WL_IwtMatrix * * Perform a LEVELS-deep separable inverse wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * ROWS and COLS indicate the size of the SOURCE & DEST matrix. * The transformed coefficients in SOURCE must be stored in the Mallat * format. * * The edge treatment is to perform periodic extension. */ public static int WL_IwtMatrix(double[,] source, double[,] dest, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { double[] tempSource; double[] tempDest; int c, r, level; /* allocate the temp arrays for columns */ tempSource = new double[rows]; tempDest = new double[rows]; /* copy the source to dest to facilitate multiple levels */ for (r = 0; r < rows; r++) { Array.Copy(source, r * cols, dest, r * cols, cols); } rows = rows / WaveletUtil.WL_pow2(levels - 1); cols = cols / WaveletUtil.WL_pow2(levels - 1); for (level = 0; level < levels; level++, rows *= 2, cols *= 2) { /* transform each column */ for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[r, c]; } if (WL_IwtVector(tempSource, ref tempDest, rows, 1, lowpass, hipass) != 0) { return(1); } for (r = 0; r < rows; r++) { dest[r, c] = tempDest[r]; } } //# ifdef DEBUG_MATRIX // fprintf(stderr, "level %d COL:\n", level); // for (r = 0; r < rows; r++) // { // for (c = 0; c < cols; c++) fprintf(stderr, "%f ", dest[r][c]); // fprintf(stderr, "\n"); // } //#endif /* transform each row */ for (r = 0; r < rows; r++) { var extract = WaveletUtil.Extract1DArray(dest, r, cols); var result = WL_IwtVector(extract, ref extract, cols, 1, lowpass, hipass); WaveletUtil.Patch1DArray(extract, ref dest, r, cols); if (result != 0) { return(1); } } //# ifdef DEBUG_MATRIX // fprintf(stderr, "level %d ROW:\n", level); // for (r = 0; r < rows; r++) // { // for (c = 0; c < cols; c++) fprintf(stderr, "%f ", dest[r][c]); // fprintf(stderr, "\n"); // } //#endif } return(0); }
/* WL_FwtVector * * Perform a LEVELS-deep forward wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. Optional * arguments indicating how edges should be treated are in ARGV. * LENGTH is the length of the SOURCE & DEST vectors. * The transformed coefficients in DEST are stored in the Mallat * representation. * * The default edge treatment is periodic extension. The option */ public static int WL_FwtVector( double[] source, ref double[] dest, int length, int levels, WL_Filter lowpass, WL_Filter hipass ) { double[] temp; /* extended source vector */ int i, j, level; int hisize = hipass.Length; int lowsize = lowpass.Length; double[] hicoefs = hipass.Coefs; double[] lowcoefs = lowpass.Coefs; double hisum, lowsum; int left = Math.Max(lowpass.Offset, hipass.Offset); int right = Math.Max(lowpass.Length - lowpass.Offset - 1, hipass.Length - hipass.Offset - 1); // These are "pointers" into arrays int hiresult; int lowresult; int hidata; int lowdata; /* allocate memory for the extended copy of source */ temp = new double[length + left + right]; /* copy source to dest to support doing multiple level transforms */ Array.Copy(source, dest, length); for (level = 0; level < levels; level++, length /= 2) { j = 0; for (i = length - left; i < length; i++) { temp[j++] = dest[i]; } for (i = 0; i < length; i++) { temp[j++] = dest[i]; } for (i = 0; i < right; i++) { temp[j++] = dest[i]; } //# ifdef DEBUG // fprintf(stderr, "level %d temp: ", level); // for (i = 0; i < length + left + right; i++) // fprintf(stderr, "%f ", temp[i]); // fprintf(stderr, "\n"); //#endif lowresult = 0; hiresult = length / 2; lowdata = left - lowpass.Offset; hidata = left - hipass.Offset; for (i = 0; i < length; i += 2, lowdata += 2, hidata += 2) { hisum = lowsum = 0; for (j = 0; j < lowsize; j++) { lowsum += temp[lowdata + j] * lowcoefs[j]; } for (j = 0; j < hisize; j++) { hisum += temp[hidata + j] * hicoefs[j]; } dest[lowresult++] = lowsum; dest[hiresult++] = hisum; } //# ifdef DEBUG // fprintf(stderr, "level %d result: ", level); // for (i = 0; i < length; i++) fprintf(stderr, "%f ", dest[i]); // fprintf(stderr, "\n"); //#endif } return(0); }
/* WL_IswtVector * * Perform a LEVELS-deep inverse symmetric wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * LENGTH is the length of the SOURCE & DEST vectors. * The coefficients in SOURCE are expected to be in the Mallat format. */ public static int WL_IswtVector( double[] source, ref double[] dest, int length, int levels, WL_Filter lowpass, WL_Filter hipass ) { int[] sgnpart; int wBound; /* Current wavelet coefficient boundary */ int tmp; double[] upLow; /* extended upsampled low frequency vector */ double[] upHi; /* extended upsampled high frequency vector */ int i, j, level; int hisize = hipass.Length; int lowsize = lowpass.Length; double[] hicoefs = hipass.Coefs; double[] lowcoefs = lowpass.Coefs; double sum; int left = Math.Max(lowpass.Offset, hipass.Offset); int right = Math.Max(lowpass.Length - lowpass.Offset - 1, hipass.Length - hipass.Offset - 1); // These are "pointers" into arrays int result; int hidata; int lowdata; sgnpart = new int[levels + 1]; /* allocate memory for the extended copies of source */ upLow = new double[length + left + right]; upHi = new double[length + left + right]; /* Determine the way the transformed signal is partitioned. */ for (level = levels, tmp = length; level > 0; level--) { sgnpart[level] = tmp / 2; tmp = (tmp + 1) / 2; } sgnpart[0] = tmp; /* copy the lowest frequency portion to dest to facilitate multiple levels */ for (i = 0; i < sgnpart[0] + sgnpart[1]; i++) { dest[i] = source[i]; } wBound = sgnpart[0]; for (level = 0; level < levels; level++) { /* upsample the source data */ for (i = 0, j = left; i < wBound; i++) { upLow[j] = dest[i]; j += 1; upLow[j] = 0; j += 1; } for (i = 0, j = left; i < sgnpart[level + 1]; i++) { upHi[j] = source[wBound + i]; j += 1; upHi[j] = 0; j += 1; } length = wBound + sgnpart[level + 1]; /* edge extension options */ if (lowsize % 2 == 1) { /* odd length filter (WSS filter) */ if (length % 2 == 0) { /* even length signal */ /* use E(1,2) for low */ for (j = 0, i = 2 * left; i > left; i--) { upLow[j++] = upLow[i]; } for (j = left + length, i = left + length - 2; i > left + length - 2 - right; i--) { upLow[j++] = upLow[i]; } /* use E(2,1) for hi */ upHi[left - 1] = 0; for (j = 0, i = 2 * left - 2; i >= left; i--) { upHi[j++] = upHi[i]; } for (j = length + left, i = left + length - 4; i > left + length - 4 - right; i--) { upHi[j++] = upHi[i]; } } else { /* odd length signal */ /* use E(1,1) for low, symmetric */ for (j = left - 1, i = left + 1; i <= 2 * left; i++) { upLow[j--] = upLow[i]; } for (j = length + left, i = length + left - 2; i > left + length - 2 - right; i--) { upLow[j++] = upLow[i]; } /* use E(2,2) for hi, symmetric */ upHi[left - 1] = 0; for (j = left - 2, i = left; i < 2 * left - 1; i++) { upHi[j--] = upHi[i]; } upHi[length + left - 1] = upHi[length + left - 3]; for (j = length + left, i = length + left - 4; i > left + length - 4 - right; i--) { upHi[j++] = upHi[i]; } } } else { /* even length filter (HS filter) */ if (length % 2 == 0) { /* even length signal */ /* use E(2,2) for low */ upLow[left - 1] = 0; for (j = 0, i = 2 * left - 2; i >= left; i--) { upLow[j++] = upLow[i]; } for (j = left + length, i = left + length - 2; i > left + length - 2 - right; i--) { upLow[j++] = upLow[i]; } /* use E(2,2) for hi, antisymmetric */ upHi[left - 1] = 0; for (j = 0, i = 2 * left - 2; i >= left; i--) { upHi[j++] = -upHi[i]; } for (j = left + length, i = left + length - 2; i > left + length - 2 - right; i--) { upHi[j++] = -upHi[i]; } } else { /* odd length signal */ /* use E(2,1) for low */ upLow[left - 1] = 0; for (j = left - 2, i = left; i < 2 * left - 1; i++) { upLow[j--] = upLow[i]; } for (j = length + left, i = length + left - 2; i > left + length - 2 - right; i--) { upLow[j++] = upLow[i]; } /* use E(2,1) for hi, antisymmetric */ upHi[left - 1] = 0; for (j = left - 2, i = left; i < 2 * left - 1; i++) { upHi[j--] = -upHi[i]; } upHi[length + left - 1] = -upHi[length + left - 5]; for (j = length + left, i = length + left - 6; i > left + length - 6 - right; i--) { upHi[j++] = -upHi[i]; } } } #if false printf("\n\n-------------------------\n"); printf("Length = %d Left = %d Right = %d\n", length, left, right); printf("upLow = "); for (i = 0; i < left; i++) { printf("%g ", upLow[i]); } printf("\n"); for (i = left; i < length + left; i++) { printf("%g ", upLow[i]); } printf("\n"); for (i = length + left; i < length + left + right; i++) { printf("%g ", upLow[i]); } printf("\nupHi = "); for (i = 0; i < left; i++) { printf("%g ", upHi[i]); } printf("\n"); for (i = left; i < length + left; i++) { printf("%g ", upHi[i]); } printf("\n"); for (i = length + left; i < length + left + right; i++) { printf("%g ", upHi[i]); } printf("\n--------------------------\n\n"); #endif /* filter the source vectors */ lowdata = left - lowpass.Offset; hidata = left - hipass.Offset; result = 0; for (i = 0; i < length; i++, lowdata++, hidata++) { sum = 0; for (j = 0; j < lowsize; j++) { sum += upLow[lowdata + j] * lowcoefs[j]; } for (j = 0; j < hisize; j++) { sum += upHi[hidata + j] * hicoefs[j]; } dest[result++] = sum; } wBound += (sgnpart[level + 1]); } return(0); }
/* WL_IwtVolume * * Perform a LEVELS-deep separable inverse wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * ROWS and COLS indicate the size of the SOURCE & DEST volume. * The transformed coefficients in SOURCE must be stored in the Mallat * format. * * The edge treatment is to perform periodic extension. */ public static int WL_IwtVolume(double[,,] source, ref double[,,] dest, int depth, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { double[] tempSource; double[] tempDest; int d, c, r, level; /* allocate the temp arrays for columns */ tempSource = new double[Math.Max(rows, depth)]; tempDest = new double[Math.Max(rows, depth)]; /* copy the source to dest to facilitate multiple levels */ for (d = 0; d < depth; d++) { for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { dest[d, r, colNum] = source[d, r, colNum]; } } } rows = rows / WaveletUtil.WL_pow2(levels - 1); cols = cols / WaveletUtil.WL_pow2(levels - 1); depth = depth / WaveletUtil.WL_pow2(levels - 1); for (level = 0; level < levels; level++, rows *= 2, cols *= 2, depth *= 2) { /* transform each column */ for (d = 0; d < depth; d++) { for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[d, r, c]; } if (WL_IwtVector(tempSource, ref tempDest, rows, 1, lowpass, hipass) != 0) { return(1); } for (r = 0; r < rows; r++) { dest[d, r, c] = tempDest[r]; } } } /* transform each row */ for (d = 0; d < depth; d++) { for (r = 0; r < rows; r++) { var extract = WaveletUtil.Extract1DArray(dest, d, r, cols); var result = WL_IwtVector(extract, ref extract, cols, 1, lowpass, hipass); WaveletUtil.Patch1DArray(extract, ref dest, d, r, cols); if (result != 0) { return(1); } } } /* transform each depth line */ for (r = 0; r < rows; r++) { for (c = 0; c < cols; c++) { for (d = 0; d < depth; d++) { tempSource[d] = dest[d, r, c]; } if (WL_IwtVector(tempSource, ref tempDest, depth, 1, lowpass, hipass) != 0) { return(1); } for (d = 0; d < depth; d++) { dest[d, r, c] = tempDest[d]; } } } } return(0); }
/* WL_IswtMatrix * * Perform a LEVELS-deep separable inverse symmetric wavelet * transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * ROWS and COLS indicate the size of the SOURCE & DEST vectors. * The transformed coefficients in SOURCE must be stored in the Mallat * format. */ public static int WL_IswtMatrix(double[,] source, ref double[,] dest, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { int[] rSplit; int[] cSplit; double[] tempSource; double[] tempDest; int c, r, level; rSplit = new int[levels + 1]; cSplit = new int[levels + 1]; /* allocate the temp arrays for columns */ tempSource = new double[rows]; tempDest = new double[rows]; /* copy the source to dest to facilitate multiple levels */ for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { dest[r, colNum] = source[r, colNum]; } } /* Determine the way the dimensions of the signal is partitioned. */ for (level = levels, c = cols, r = rows; level > 0; level--) { rSplit[level] = r / 2; r = (r + 1) / 2; cSplit[level] = c / 2; c = (c + 1) / 2; } rSplit[0] = r; cSplit[0] = c; rows = rSplit[0]; cols = cSplit[0]; for (level = 1; level < levels + 1; level++) { rows += (rSplit[level]); cols += (cSplit[level]); /* transform each column */ for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[r, c]; } if (WL_IswtVector(tempSource, ref tempDest, rows, 1, lowpass, hipass) != 0) { return(1); } for (r = 0; r < rows; r++) { dest[r, c] = tempDest[r]; } } //# ifdef DEBUG_MATRIX // fprintf(stderr, "level %d COL:\n", level); // for (r = 0; r < rows; r++) // { // for (c = 0; c < cols; c++) fprintf(stderr, "%f ", dest[r][c]); // fprintf(stderr, "\n"); // } //#endif /* transform each row */ for (r = 0; r < rows; r++) { var extract = WaveletUtil.Extract1DArray(dest, r, cols); var result = WL_IswtVector(extract, ref extract, cols, 1, lowpass, hipass); WaveletUtil.Patch1DArray(extract, ref dest, r, cols); if (result != 0) { return(1); } } //# ifdef DEBUG_MATRIX // fprintf(stderr, "level %d ROW:\n", level); // for (r = 0; r < rows; r++) // { // for (c = 0; c < cols; c++) fprintf(stderr, "%f ", dest[r][c]); // fprintf(stderr, "\n"); // } //#endif } return(0); }
/* WL_FswtVector * * Perform a LEVELS-deep symmetric forward wavelet transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * LENGTH is the length of the SOURCE & DEST vectors. * The transformed coefficients in DEST are stored in the Mallat * representation. */ public static int WL_FswtVector( double[] source, ref double[] dest, int length, int levels, WL_Filter lowpass, WL_Filter hipass ) { double[] temp; /* extended source vector */ int i, j, level; int hisize = hipass.Length; int lowsize = lowpass.Length; double[] hicoefs = hipass.Coefs; double[] lowcoefs = lowpass.Coefs; double hisum, lowsum; int left = Math.Max(lowpass.Offset, hipass.Offset); int right = Math.Max(lowpass.Length - lowpass.Offset - 1, hipass.Length - hipass.Offset - 1); // These are "pointers" into arrays int hiresult; int lowresult; int hidata; int lowdata; /* allocate memory for the extended copy of source */ temp = new double[length + left + right]; /* copy source to dest to support doing multiple level transforms */ Array.Copy(source, dest, length); for (level = 0; level < levels; level++) { /* make symmetric extension of dest vector */ if (lowsize % 2 == 1) { /* odd length filter (WSS filter), use E(1,1) extension */ j = 0; for (i = left; i > 0; i--) { temp[j++] = dest[i]; } for (i = 0; i < length; i++) { temp[j++] = dest[i]; } for (i = length - 2; i > length - 2 - right; i--) { temp[j++] = dest[i]; } } else { /* even length filter (HS filter), use E(2,2) extension */ j = 0; for (i = left - 1; i >= 0; i--) { temp[j++] = dest[i]; } for (i = 0; i < length; i++) { temp[j++] = dest[i]; } for (i = length - 1; i >= length - right; i--) { temp[j++] = dest[i]; } } /* filter the temp vector */ lowresult = 0; hiresult = (length + 1) / 2; lowdata = left - lowpass.Offset; hidata = left - hipass.Offset; for (i = 0; i < length - 1; i += 2) { hisum = lowsum = 0; for (j = 0; j < lowsize; j++) { lowsum += temp[lowdata + j] * lowcoefs[j]; } for (j = 0; j < hisize; j++) { hisum += temp[hidata + j] * hicoefs[j]; } dest[lowresult++] = lowsum; dest[hiresult++] = hisum; lowdata += 2; hidata += 2; } /* Compute extra low-pass coefficient if signal is odd */ if ((length % 2) != 0) { lowsum = 0; for (j = 0; j < lowsize; j++) { lowsum += temp[lowdata + j] * lowcoefs[j]; } dest[lowresult] = lowsum; } length = (length + 1) / 2; } return(0); }
/* WL_IswtVolume * * Perform a LEVELS-deep separable inverse symmetric wavelet * transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in DEST. * DEPTH, ROWS and COLS indicate the size of the SOURCE & DEST volumes. * The transformed coefficients in SOURCE must be stored in the Mallat * format. */ public static int WL_IswtVolume(double[,,] source, ref double[,,] dest, int depth, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { int[] dSplit; int[] rSplit; int[] cSplit; double[] tempSource; double[] tempDest; int d, c, r, level; rSplit = new int[levels + 1]; cSplit = new int[levels + 1]; dSplit = new int[levels + 1]; /* allocate the temp arrays for columns */ tempSource = new double[Math.Max(depth, rows)]; tempDest = new double[Math.Max(depth, rows)]; /* copy the source to dest to facilitate multiple levels */ for (d = 0; d < depth; d++) { for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { dest[d, r, colNum] = source[d, r, colNum]; } } } /* Determine the way the dimensions of the signal is partitioned. */ for (level = levels, c = cols, r = rows, d = depth; level > 0; level--) { rSplit[level] = r / 2; r = (r + 1) / 2; cSplit[level] = c / 2; c = (c + 1) / 2; dSplit[level] = d / 2; d = (d + 1) / 2; } rSplit[0] = r; cSplit[0] = c; dSplit[0] = d; rows = rSplit[0]; cols = cSplit[0]; depth = dSplit[0]; for (level = 1; level < levels + 1; level++) { rows += (rSplit[level]); cols += (cSplit[level]); depth += (dSplit[level]); /* transform each row */ for (d = 0; d < depth; d++) { for (r = 0; r < rows; r++) { var extract = WaveletUtil.Extract1DArray(dest, d, r, cols); var result = WL_IswtVector(extract, ref extract, cols, 1, lowpass, hipass); WaveletUtil.Patch1DArray(extract, ref dest, d, r, cols); if (result != 0) { return(1); } } } /* transform each column */ for (d = 0; d < depth; d++) { for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[d, r, c]; } if (WL_IswtVector(tempSource, ref tempDest, rows, 1, lowpass, hipass) != 0) { return(1); } for (r = 0; r < rows; r++) { dest[d, r, c] = tempDest[r]; } } } /* transform each depth line */ for (r = 0; r < rows; r++) { for (c = 0; c < cols; c++) { for (d = 0; d < depth; d++) { tempSource[d] = dest[d, r, c]; } if (WL_IswtVector(tempSource, ref tempDest, depth, 1, lowpass, hipass) != 0) { return(1); } for (d = 0; d < depth; d++) { dest[d, r, c] = tempDest[d]; } } } } return(0); }
/******************************************************************** * * Redundant Wavelet Transforms for Vectors * *******************************************************************/ /* WL_FrwtVector * * Perform a levels-deep forward redundant transform of vector SOURCE using * the filters HIPASS and LOWPASS, storing results in a matrix DEST. * LENGTH is the length of the SOURCE vector & the rows in DEST.printf("here pow2:%d level:%d\n",pow2,level); * * The transformed coefficients in DEST are stored using an overcomplete * representation, each row representing a level in the multiresolution * pyramid with coarse approximation in zeroth row and the detail signals * at level i in the ith row. */ public static int WL_FrwtVector( double[] source, ref double[,] dest, int length, int levels, WL_Filter lowpass, WL_Filter hipass ) { double[] temp; /* extended source vector */ int i, j, level, left, right, pow2; int hisize, lowsize; double[] hicoefs; double[] lowcoefs; int lowoffset, hioffset; // These are "pointers" into arrays int hiresult; int lowresult; int hidata; int lowdata; /* allocate memory for the extended copy of source */ pow2 = WaveletUtil.WL_pow2(levels - 1); lowoffset = lowpass.Offset * pow2; hioffset = hipass.Offset * pow2; lowsize = (lowpass.Length - 1) * pow2 + 1; hisize = (hipass.Length - 1) * pow2 + 1; left = Math.Max(lowoffset, hioffset); right = Math.Max(lowsize - lowoffset - 1, hisize - hioffset - 1); temp = new double[length + (left + right) * pow2]; /* allocate memory for the lowpass & highpass filter coefficients */ hicoefs = new double[hisize * pow2]; lowcoefs = new double[lowsize * pow2]; /* copy source to dest to support doing multiple level transforms */ for (int z = 0; z < length; z++) { dest[0, z] = source[z]; } for (pow2 = 1, level = 0; level < levels; level++, pow2 *= 2) { /* dilate the filters */ Dilate_filter(lowpass.Coefs, ref lowcoefs, lowpass.Length, level); Dilate_filter(hipass.Coefs, ref hicoefs, hipass.Length, level); lowoffset = lowpass.Offset * pow2; hioffset = hipass.Offset * pow2; lowsize = (lowpass.Length - 1) * pow2 + 1; hisize = (hipass.Length - 1) * pow2 + 1; left = Math.Max(lowoffset, hioffset); right = Math.Max(lowsize - lowoffset - 1, hisize - hioffset - 1); /* make periodic extension of dest vector */ j = 0; for (i = length - left; i < length; i++) { temp[j++] = dest[0, i]; } for (i = 0; i < length; i++) { temp[j++] = dest[0, i]; } for (i = 0; i < right; i++) { temp[j++] = dest[0, i]; } /* convolve the data */ lowresult = 0; hiresult = 0; lowdata = left - lowoffset; hidata = left - hioffset; for (i = 0; i < length; i++, lowdata++, hidata++) { double hisum = 0, lowsum = 0; for (j = 0; j < lowsize; j++) { lowsum += temp[lowdata + j] * lowcoefs[j]; } for (j = 0; j < hisize; j++) { hisum += temp[hidata + j] * hicoefs[j]; } dest[0, lowresult++] = lowsum; dest[level + 1, hiresult++] = hisum; } } return(1); }
/* WL_IrwtVolume * * Perform a LEVELS-deep separable inverse redundant transform of SOURCE using * the filters HIPASS and LOWPASS, storing results in matrix DEST. * ROWS and COLS indicate the size of the rows and columns of volume SOURCE * and the size of matrix DEST. * The transformed coefficients in SOURCE are stored using an overcomplete * representation, each ROWSxCOLS matrix representing a level in the * multiresolution pyramid with coarse approximation in zeroth matrix and * the 3 detail signals at level i in matrix 3*i+j, where 1<=j<=3. * The input volume SOURCE has depth levels+1. */ public static int WL_IrwtVolume( double[,,] source, ref double[,] dest, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass ) { double[] tempDest; double[,] HighMatrix; double[,] RowMatrix; double[,] ColMatrix; int c, r, level; int hori, vert, diag; /* allocate the temp arrays to hold 1-D results */ RowMatrix = new double[2, cols]; ColMatrix = new double[2, rows]; HighMatrix = new double[rows, cols]; tempDest = new double[rows]; /* copy the source to dest to facilitate multiple levels */ for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { dest[r, colNum] = source[0, r, colNum]; } } for (level = levels; level >= 1; level--) { /* setup indices to horizontal,vertical & diagonal detail signals */ vert = 3 * (level - 1) + 1; hori = vert + 1; diag = hori + 1; /* transform each column */ /* first, run the inverse transform using the lowpass output */ /* from the 1D forward redundant transform along the columns */ for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { ColMatrix[0, r] = dest[r, c]; ColMatrix[1, r] = source[vert, r, c]; } if (WL_IrwtMatrix(ColMatrix, ref tempDest, rows, level, lowpass, hipass) != 1) { return(0); } for (r = 0; r < rows; r++) { dest[r, c] = tempDest[r]; } } /* now, for the high pass output */ for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { ColMatrix[0, r] = source[hori, r, c]; ColMatrix[1, r] = source[diag, r, c]; } if (WL_IrwtMatrix(ColMatrix, ref tempDest, rows, level, lowpass, hipass) != 1) { return(0); } for (r = 0; r < rows; r++) { HighMatrix[r, c] = tempDest[r]; } } /* transform each row */ for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { RowMatrix[0, colNum] = dest[r, colNum]; RowMatrix[1, colNum] = HighMatrix[r, colNum]; } var extract = WaveletUtil.Extract1DArray(dest, r, cols); var result = WL_IrwtMatrix(RowMatrix, ref extract, cols, level, lowpass, hipass); WaveletUtil.Patch1DArray(extract, ref dest, r, cols); if (result != 1) { return(0); } } } return(1); }
/*************************************************************** * * Redundant Wavelet Transforms for Matrices * **************************************************************/ /* WL_FrwtMatrix * * Perform a LEVELS-deep separable forward redundant wavelet transform of * SOURCE using the filters HIPASS and LOWPASS, storing results in volume * DEST. * ROWS and COLS indicate the size of the SOURCE matrix and rows and * columns of volume DEST. * The transformed coefficients in DEST are stored using an overcomplete * representation: each ROWSxCOLS matrix representing a level in the * multiresolution pyramid with coarse approximation in zeroth matrix and * the 3 detail signals at level i in matrix 3*i+j, where 1<=j<=3. * The output volume DEST has depth 3*levels+1. */ public static int WL_FrwtMatrix(double[,] source, ref double[,,] dest, int rows, int cols, int levels, WL_Filter lowpass, WL_Filter hipass) { double[] tempSource; double[,] RowMatrix; double[,] ColMatrix; int c, r, level; int hori, vert, diag; /* allocate the temp arrays to hold 1-D results */ RowMatrix = new double[2, cols]; ColMatrix = new double[2, rows]; tempSource = new double[rows]; /* copy the source to dest to facilitate multiple levels */ for (r = 0; r < rows; r++) { for (int colNum = 0; colNum < cols; colNum++) { dest[0, r, colNum] = source[r, colNum]; } } for (level = 1; level <= levels; level++) { /* setup indices to horizontal,vertical & diagonal detail signals */ vert = 3 * (level - 1) + 1; hori = vert + 1; diag = hori + 1; /* transform each row */ for (r = 0; r < rows; r++) { var extract = WaveletUtil.Extract1DArray(dest, 0, r, cols); var result = WL_FrwtVector(extract, ref RowMatrix, cols, level, lowpass, hipass); if (result != 1) { return(0); } for (int colNum = 0; colNum < cols; colNum++) { dest[0, r, colNum] = RowMatrix[0, colNum]; dest[hori, r, colNum] = RowMatrix[1, colNum]; } } /* transform each column */ /* first, run the transform on the lowpass output from the */ /* frwt algorithm run on the rows */ for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[0, r, c]; } if (WL_FrwtVector(tempSource, ref ColMatrix, rows, level, lowpass, hipass) != 1) { return(0); } for (r = 0; r < rows; r++) { dest[0, r, c] = ColMatrix[0, r]; dest[vert, r, c] = ColMatrix[1, r]; } } /* now, for the high pass output */ for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { tempSource[r] = dest[hori, r, c]; } if (WL_FrwtVector(tempSource, ref ColMatrix, rows, level, lowpass, hipass) != 1) { return(0); } for (r = 0; r < rows; r++) { dest[hori, r, c] = ColMatrix[0, r]; dest[diag, r, c] = ColMatrix[1, r]; } } } return(1); }
/* WL_IrwtMatrix * * Perform a LEVELS-deep inverse redundant wavelet transform of matrix SOURCE * using the filters HIPASS and LOWPASS, storing results in vector * DEST. * The coefficients in SOURCE are expected to be stored in the * overcomplete representation, each row representing a level in the * multiresolution pyramid with coarse approximation in zeroth row and * the detail signals at level i in the ith row. * LENGTH is the length of the rows of SOURCE & of the vector DEST. */ public static int WL_IrwtMatrix(double[,] source, ref double[] dest, int length, int levels, WL_Filter lowpass, WL_Filter hipass) { int i, j, level, left, right, pow2; int hisize, lowsize; int lowoffset, hioffset; double[] hitemp; double[] lowtemp; /* extended source vector */ double[] hicoefs; double[] lowcoefs; // These are "pointers" into arrays int hidata; int lowdata; int result; /* allocate memory for the extended copies of hi & low source vectors */ pow2 = WaveletUtil.WL_pow2(levels - 1); lowoffset = lowpass.Offset * pow2; hioffset = hipass.Offset * pow2; lowsize = (lowpass.Length - 1) * pow2 + 1; hisize = (hipass.Length - 1) * pow2 + 1; left = Math.Max(lowoffset, hioffset); right = Math.Max(lowsize - lowoffset - 1, hisize - hioffset - 1); hitemp = new double[length + (left + right) * pow2]; lowtemp = new double[length + (left + right) * pow2]; /* allocate memory for the lowpass & highpass filter coefficients */ hicoefs = new double[hisize * pow2]; lowcoefs = new double[lowsize * pow2]; /* copy the lowpass signal to dest to facilitate multiple levels */ for (i = 0; i < length; i++) { dest[i] = source[0, i]; } for (pow2 = WaveletUtil.WL_pow2(levels - 1), level = levels - 1; level >= 0; level--, pow2 /= 2) { /* dilate the filters */ Dilate_filter(lowpass.Coefs, ref lowcoefs, lowpass.Length, level); Dilate_filter(hipass.Coefs, ref hicoefs, hipass.Length, level); lowoffset = lowpass.Offset * pow2; hioffset = hipass.Offset * pow2; lowsize = (lowpass.Length - 1) * pow2 + 1; hisize = (hipass.Length - 1) * pow2 + 1; left = Math.Max(lowoffset, hioffset); right = Math.Max(lowsize - lowoffset - 1, hisize - hioffset - 1); /* make periodic extension of dest vector */ j = 0; for (i = length - left; i < length; i++, j++) { lowtemp[j] = dest[i]; hitemp[j] = source[level + 1, i]; } for (i = 0; i < length; i++, j++) { lowtemp[j] = dest[i]; hitemp[j] = source[level + 1, i]; } for (i = 0; i < right; i++, j++) { lowtemp[j] = dest[i]; hitemp[j] = source[level + 1, i]; } /* convolve the data */ result = 0; lowdata = left - lowoffset; hidata = left - hioffset; for (i = 0; i < length; i++, lowdata++, hidata++) { double hisum = 0, lowsum = 0; for (j = 0; j < lowsize; j++) { lowsum += lowtemp[lowdata + j] * lowcoefs[j]; } for (j = 0; j < hisize; j++) { hisum += hitemp[hidata + j] * hicoefs[j]; } dest[result++] = (lowsum + hisum) * 0.5; } } return(1); }