/// <summary> /// Inverse Haar Transform of a 2D image to a Matrix. /// This is using the tensor product layout. /// Performance is also quite fast. /// Note that the input array must be a square matrix of dimension 2n x 2n where n is an integer /// </summary> /// <param name="image">2D array</param> /// <param name="disableMatrixDimensionCheck">True if matrix dimension check should be turned off</param> /// <returns>Matrix with inverse haar transform</returns> public static Matrix InverseHaarWaveletTransform(double[][] image, bool disableMatrixDimensionCheck=false) { Matrix imageMatrix = new Matrix(image); // Check that the input matrix is a square matrix of dimension 2n x 2n (where n is an integer) if (!disableMatrixDimensionCheck && !imageMatrix.IsSymmetric() && !MathUtils.IsPowerOfTwo(image.Length)) { throw new Exception("Input matrix is not symmetric or has dimensions that are a power of two!"); } double[] imagePacked = imageMatrix.GetColumnPackedCopy(); HaarTransform.haar_2d_inverse(imageMatrix.Rows, imageMatrix.Columns, imagePacked); Matrix inverseHaarMatrix = new Matrix(imagePacked, imageMatrix.Rows); return inverseHaarMatrix; }
public static void TestHaarTransform() { double[][] mat = Get2DTestData(); Matrix matrix = new Matrix(mat); //matrix.Print(); double[] packed = matrix.GetColumnPackedCopy(); HaarTransform.r8mat_print (matrix.Rows, matrix.Columns, packed, " Input array packed:"); HaarTransform.haar_2d(matrix.Rows, matrix.Columns, packed); HaarTransform.r8mat_print (matrix.Rows, matrix.Columns, packed, " Transformed array packed:"); double[] w = HaarTransform.r8mat_copy_new(matrix.Rows, matrix.Columns, packed); HaarTransform.haar_2d_inverse (matrix.Rows, matrix.Columns, w); HaarTransform.r8mat_print (matrix.Rows, matrix.Columns, w, " Recovered array W:"); Matrix m = new Matrix(w, matrix.Rows); //m.Print(); }
/// <summary> /// Transforms one window of MFCCs. The following steps are /// performed: <br> /// <br> /// (1) normalized power fft with hanning window function<br> /// (2) convert to Mel scale by applying a mel filter bank<br> /// (3) convertion to db<br> /// (4) finally a DCT is performed to get the mfcc<br> ///<br> /// This process is mathematical identical with the process described in [1]. /// </summary> /// <param name="window">double[] data to be converted, must contain enough data for /// one window</param> /// <param name="start">int start index of the window data</param> /// <returns>double[] the window representation in Sone</returns> public double[] ProcessWindow(double[] window, int start) { //number of unique coefficients, and the rest are symmetrically redundant int fftSize = (windowSize / 2) + 1; //check start if(start < 0) throw new Exception("start must be a positive value"); //check window size if(window == null || window.Length - start < windowSize) throw new Exception("the given data array must not be a null value and must contain data for one window"); //just copy to buffer for (int j = 0; j < windowSize; j++) buffer[j] = window[j + start]; //perform power fft normalizedPowerFFT.Transform(buffer, null); //use all coefficient up to the nequist frequency (ceil((fftSize+1)/2)) Matrix x = new Matrix(buffer, windowSize); x = x.GetMatrix(0, fftSize-1, 0, 0); //fftSize-1 is the index of the nyquist frequency //apply mel filter banks x = melFilterBanks.Times(x); //to db double log10 = 10 * (1 / Math.Log(10)); // log for base 10 and scale by factor 10 x.ThrunkAtLowerBoundary(1); x.LogEquals(); x.TimesEquals(log10); //compute DCT x = dctMatrix.Times(x); return x.GetColumnPackedCopy(); }