/* 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_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_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); }
/******************************************************************** * * 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_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); }