/* DILATE_FILTER * * Dilates the input vector SOURCE by INDEX, storing the result in DEST. * The length of the SOURCE vector is LENGTH. */ public static void Dilate_filter(double[] source, ref double[] dest, int length, int index) { int i, j, k, power; power = WaveletUtil.WL_pow2(index); for (i = 0, j = 0; i < length; i++) { dest[j++] = source[i]; for (k = 1; k < power; k++) { dest[j++] = (double)0; } } }
/****************************************************************************** * * MALLAT STORAGE FORMAT DATA STRUCTURE UTILITIES * ******************************************************************************/ /* BoundingBox * * Calculates the left, right, top, and bottom boundary of the * detail signal for the described image. * * ROWS the number of rows in the full image * COLS the number of columns in the full image * LEVEL the level of the detail signal in question * DETAIL the id of the detail signal in question * LEFT, RIGHT, TOP, BOTTOM the sides of the detail signal, calculated * by this function */ public static int WL_BoundingBox(int rows, int cols, int level, int detail, out int left, out int right, out int top, out int bottom) { int rowSize; /* size of each row at this level */ int colSize; /* size of each column at this level */ /* compute bounding box of gamma quadrant */ rowSize = cols / WaveletUtil.WL_pow2(level); colSize = rows / WaveletUtil.WL_pow2(level); left = right = top = bottom = 0; switch (detail) { case 0: /* upper right quadrant */ left = rowSize; right = 2 * rowSize; top = 0; bottom = colSize; break; case 1: /* lower left quadrant */ left = 0; right = rowSize; top = colSize; bottom = 2 * colSize; break; case 2: /* lower right quadrant */ left = rowSize; right = 2 * rowSize; top = colSize; bottom = 2 * colSize; break; default: Trace.WriteLine("WL_BoundingBox: unexpected detail value."); return(1); } return(0); }
/* 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_SBFilterLoad * * Loads a subband filter from a data file. */ public static int WL_SBFilterLoad(string fileName, string filterName, WL_SubbandFilter[,] newFilter) { int length, rows, cols; double[] data; // "Pointer" into data int d; int i; int coef; /* read in the data */ if (WaveletUtil.WL_ReadAsciiDataFile(fileName, out rows, out cols, out data) != 0) { return(1); } length = rows * cols; d = 0; /* create a new filter */ WL_SubbandFilter filter = new WL_SubbandFilter { Info = new WL_Struct { Name = filterName, Type = "sbfilter", PList = null } }; /* fill in the data for the four filters */ for (i = 0; i < 4; i++) { /* is there header data for a filter ? */ if (length - 2 < 0) { Trace.WriteLine("WL_SBFilterLoad : Bad descriptor file: not enough data"); return(1); } filter.Filters[i].Length = (int)(data[d++] + 0.5); filter.Filters[i].Offset = (int)(data[d++] + 0.5); length -= 2; /* is the offset legal? */ if ((filter.Filters[i].Offset < 0) || (filter.Filters[i].Offset > filter.Filters[i].Length)) { Trace.WriteLine("WL_SBFilterLoad : Bad descriptor file: not enough data"); return(1); } /* is there enough data left for this filter? */ if (length < filter.Filters[i].Length) { throw new Exception("WL_SBFilterLoad : Bad descriptor file: not enough data"); } /* store the filter coefficients into an array */ filter.Filters[i].Coefs = new double[filter.Filters[i].Length]; for (coef = 0; coef < filter.Filters[i].Length; coef++) { filter.Filters[i].Coefs[coef] = data[d++]; length--; } } 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_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_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_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_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); }