C# Convolution Example

← All NMath Code Examples

 

using System;
using System.Globalization;
using System.Threading;
using System.Text;

using CenterSpace.NMath.Core;

namespace CenterSpace.NMath.Examples.CSharp
{
  /// <summary>
  /// .NET example in C# showing how to use the convolution classes.
  /// </summary>
  class ConvolutionExample
  {
    static void Main( string[] args )
    {

      # region moving average filter with convolution

      //
      // Simple example to compute a moving average filter with convolution
      //

      // Create some random signal data.
      var rand = new RandGenMTwist( 4230987 );
      var data = new DoubleVector( 500, rand );

      // Create a simple averaging kernel.
      var kernel = new DoubleVector( "[.2 .2 .2 .2 .2]" );

      // Create the convolution class.
      var convolution = new Double1DConvolution( kernel, data.Length );

      // Compute the convolution.
      DoubleVector smoothed = convolution.Convolve( data );

      Console.WriteLine();

      Console.WriteLine();
      Console.WriteLine( "Double precision 1D convolution computed." );
      Console.WriteLine( "-----------------------------------------\n" );

      #endregion

      # region single precision convolution example

      //
      // Simple example to compute a single precision convolution
      //

      // Create some random signal data.
      var dataF = new FloatVector( "[ 1, 2, 3, 7, 2, 1 ]" );

      // Create the averaging kernel
      float[] kernelF = { .2f, .2f, .2f, .2f, .2f, };

      // Create the convolution class and compute the convolution
      // When only the kernel and data length is specified in this constructor, the 
      // convolution results are truncated to match the length of the input data.
      // This is typically what most users need.
      var convolutionF = new Float1DConvolution( new FloatVector( kernelF ), dataF.Length );

      // Using the convolution length allows up to exactly size the output data buffer.
      var smoothedF = new FloatVector( convolutionF.Length );

      // Execute the convolution
      convolutionF.Convolve( dataF, ref smoothedF );

      // Trim the results of the convolution where the kernel fully overlapped the data set.
      // NOTE: This trim just makes a new view into the convolution result, no data is copied.
      FloatVector trimmedKernelSmoothedDataF = convolutionF.TrimConvolution( smoothedF, ConvolutionBase.Windowing.FullKernelOverlap );

      // Trim the results to the center of the convolution that matches the input data size.
      FloatVector trimmedDataSmoothedDataF = convolutionF.TrimConvolution( smoothedF, ConvolutionBase.Windowing.CenterWindow );

      // Write out results
      Console.WriteLine( "Convolution results showing smoothed data." );
      Console.WriteLine( "Input data = " );
      Console.WriteLine( dataF.ToString() );

      Console.WriteLine( "Convolution kernel = " );
      Console.WriteLine( new FloatVector( kernelF ).ToString() );

      Console.WriteLine( "Convolved data = " );
      Console.WriteLine( smoothedF.ToString() );

      Console.WriteLine( "Trimmed smooth data to fully overlapping kernel = " );
      Console.WriteLine( trimmedKernelSmoothedDataF.ToString() );

      Console.WriteLine( "Trimmed smooth data centered on data length = " );
      Console.WriteLine( trimmedDataSmoothedDataF.ToString() );

      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      # region complex double precision convolution example

      //
      // Simple example to compute a complex double precision convolution with real data.
      //

      // Create some real signal data and complex kernel
      // Naturally the data could be complex, and the following code would be unchanged.
      var kernelZ = new DoubleComplexVector( "(1,1) (2,2) (3,3) (4,4)" );
      var dataZ = new DoubleComplexVector( "(1,0) (2,0) (3,0) (4,0) (5,0) (6,0)" );

      // Create the convolution class and compute the convolution
      // When only the kernel and data length is specified in this constructor, the 
      // convolution results are truncated to match the length of the input data.
      // This is typically what most users need, with the convolution edge effects removed.
      var convolutionZ = new DoubleComplex1DConvolution( kernelZ, dataZ.Length );
      DoubleComplexVector smoothedDataZ = convolutionZ.Convolve( dataZ );

      // Write out results
      Console.WriteLine( "Complex convolution results with a complex kernel and real data." );
      Console.WriteLine( "Input data = " );
      Console.WriteLine( dataZ.ToString() );

      Console.WriteLine( "Complex convolution kernel = " );
      Console.WriteLine( kernelZ.ToString() );

      Console.WriteLine( "Convolved data = " );
      Console.WriteLine( smoothedDataZ.ToString() );

      Console.WriteLine( "-----------------------------------\n" );

      #endregion

      # region single precision convolution with full length output and strided kernel

      //
      // Simple example to compute a single precision convolution with full length output
      // and a strided kernel.
      //

      // Create some random signal data.
      float[] dataFS = { 1, 2, 3, 7, 2, 1 };

      // Create the strided averaging kernel
      float[] kernelFS = { .2f, -1f, .2f, -1f, .2f, -1f, .2f, -1f, .2f, };

      // Create the convolution class and compute the convolution
      // Using this constructor we can specific an offset and strided kernel, the length
      // of the data, and the output length.  To find the full length of the
      // convolution data, use the Float1DConvolution.OutputLength property as seen below.
      // (This may be shorter than the length specified in this constructor.)
      var convolutionFS = new Float1DConvolution( kernelFS, 0, 2, dataFS.Length );

      // Do the convolution and get the generated result.
      float[] smoothedDataFS = convolutionFS.Convolve( dataFS );

      // Write out results
      Console.WriteLine( "Convolution results with a 2-strided kernel." );
      Console.WriteLine( "Input data = " );
      Console.Write( "[ " );
      for ( int i = 0; i < dataFS.Length; i++ )
      {
        Console.Write( "{0,2:0.#} ", dataFS[i] );
      }
      Console.WriteLine( "]" );

      Console.WriteLine( "Strided convolution kernel = " );
      Console.Write( "[ " );
      for ( int i = 0; i < kernelFS.Length; i++ )
      {
        Console.Write( "{0,2:0.#} ", kernelFS[i] );
      }
      Console.WriteLine( "]" );

      Console.WriteLine( "Convolved data = " );
      Console.Write( "[ " );
      for ( int i = 0; i < convolutionFS.Length; i++ )
      {
        Console.Write( "{0,2:0.#} ", smoothedDataFS[i] );
      }
      Console.WriteLine( "]" );

      Console.WriteLine( "-----------------------------------\n" );

      #endregion


      Console.WriteLine();
      Console.WriteLine( "Finished. Press Enter Key." );
      Console.Read();
    }
  }
}

← All NMath Code Examples
Top