Example #1
0
SeparableFilter KernelFilter::AsSeparableFilter( float tolerance ) const
{
   if ( IsEmpty() )
      return SeparableFilter();

   FSVD svd( coefficients );

   // Find the largest singular value
   int i = svd.IndexOfLargestSingularValue();

   // Scaling factor to preserve the original filter weight
   float k = Sqrt( svd.W[i] );

   // Column vector
   FVector v = svd.U.ColumnVector( i );
   v *= k;

   // Row vector
   FVector h = svd.V.ColumnVector( i );
   h *= k;

   // Product matrix
   FMatrix A = FMatrix::FromColumnVector( v ) * FMatrix::FromRowVector( h );

   // Verify separability
   const float* a = A.Begin();
   const float* b = coefficients.Begin();
   const float* c = coefficients.End();
   for ( ; b < c; ++a, ++b )
      if ( Abs( *a - *b ) > tolerance )
         return SeparableFilter();

   return SeparableFilter( h, v, filterName );
}
Example #2
0
void FilterParser::Parse( const token_list& tokens )
{
   filters.Clear();

   int filterType = UnknownFilterType;
   String filterName;
   int filterSize = 0;
   KernelFilter::coefficient_matrix    filterMatrix;
   SeparableFilter::coefficient_vector rowVector, colVector;

   int state = FilterTypeState;

   for ( token_list::const_iterator i = tokens.Begin(); i != tokens.End(); )
   {
      switch ( state )
      {
      case FilterTypeState:
         {
            if ( i->token == "KernelFilter" )
               filterType = KernelFilterType;
            else if ( i->token == "SeparableFilter" )
               filterType = SeparableFilterType;
            else if ( i->token == '{' || i->token == '}' )
               PARSE_ERROR( "Misplaced bracket", i );
            else if ( !i->token.IsValidIdentifier() )
               PARSE_ERROR( "Invalid filter type \'" + i->token + '\'', i );
            else
               PARSE_ERROR( "Unknown filter type \'" + i->token + '\'', i );

            if ( ++i == tokens.End() || i->token != '{' )
               PARSE_ERROR( "Expected left bracket", i );
            state = FilterParameterState;

            ++i;
         }
         break;

      case FilterParameterState:
         {
            if ( i->token == '}' )
            {
               if ( filterName.IsEmpty() )
                  PARSE_ERROR( "Missing filter name", i );
               if ( filterSize == 0 )
                  PARSE_ERROR( "Empty filter definition", i );

               if ( filterType == KernelFilterType )
               {
                  if ( filterMatrix.IsEmpty() )
                     PARSE_ERROR( "Missing kernel filter coefficients", i );

                  filters.Add( Filter( KernelFilter( filterMatrix, filterName ) ) );
               }
               else if ( filterType == SeparableFilterType )
               {
                  if ( rowVector.IsEmpty() || colVector.IsEmpty() )
                     PARSE_ERROR( "Missing separable filter coefficients", i );

                  filters.Add( Filter( SeparableFilter( rowVector, colVector, filterName ) ) );
               }
               else
                  PARSE_ERROR( "Internal parser error", i );

               filterName.Clear();
               filterSize = 0;
               filterMatrix = KernelFilter::coefficient_matrix();
               rowVector = colVector = SeparableFilter::coefficient_vector();

               state = FilterTypeState;
               ++i;
            }
            else
            {
               token_list::const_iterator j = i; ++j;
               token_list::const_iterator k = tokens.End();
               CaptureParameterValueTokens( j, k );
               int n = Distance( j, k );

               if ( i->token == "name" )
               {
                  if ( n == 0 )
                     PARSE_ERROR( "Expected a filter name", i );
                  if ( !filterName.IsEmpty() )
                     PARSE_ERROR( "Duplicate filter name", i );
                  filterName = j->token;
                  for ( ; ++j < k; )
                     filterName += ' ' + j->token;
               }
               else if ( i->token == "coefficients" )
               {
                  if ( filterType != KernelFilterType )
                     PARSE_ERROR( "Invalid kernel filter parameter", i );
                  if ( !filterMatrix.IsEmpty() )
                     PARSE_ERROR( "Duplicate kernel filter coefficients", i );

                  token_list::const_iterator p = j;
                  GenericVector<KernelFilter::coefficient> C( n );
                  for ( KernelFilter::coefficient* c = C.Begin(); c < C.End(); ++c, ++p )
                     *c = p->token.ToFloat();

                  int numberOfCoefficients = filterSize*filterSize;
                  if ( numberOfCoefficients != 0 )
                  {
                     if ( numberOfCoefficients != n )
                        PARSE_ERROR( "Incongruent kernel filter size; expected " + String( numberOfCoefficients ) + " coefficients", j );
                  }
                  else
                  {
                     filterSize = TruncI( Sqrt( double( n ) ) );
                     if ( filterSize*filterSize != n )
                        PARSE_ERROR( "Non-square kernel filter defined", j );
                     if ( filterSize < 3 )
                        PARSE_ERROR( "The kernel filter is too small - 3x3 is the minimum required", j );
                     if ( (filterSize & 0x01) == 0 )
                        PARSE_ERROR( "Invalid even kernel filter dimension (" + String( filterSize ) + ')', j );
                  }

                  filterMatrix = KernelFilter::coefficient_matrix( C.Begin(), filterSize, filterSize );
                  j = p;
               }
               else if ( i->token == "row-vector" )
               {
                  if ( filterType != SeparableFilterType )
                     PARSE_ERROR( "Invalid separable filter parameter", i );
                  if ( !rowVector.IsEmpty() )
                     PARSE_ERROR( "Duplicate row vector specification", i );

                  token_list::const_iterator p = j;
                  rowVector = SeparableFilter::coefficient_vector( n );
                  for ( SeparableFilter::coefficient* c = rowVector.Begin(); c < rowVector.End(); ++c, ++p )
                     *c = p->token.ToFloat();

                  if ( filterSize != 0 )
                  {
                     if ( filterSize != n )
                        PARSE_ERROR( "Incongruent separable row filter length; expected " + String( filterSize ) + " coefficients", j );
                  }
                  else
                  {
                     if ( n < 3 )
                        PARSE_ERROR( "Too few row filter coefficients specified - three or more coefficients are required", j );
                     if ( (n & 0x01) == 0 )
                        PARSE_ERROR( "Invalid even row filter length (" + String( n ) + ')', j );
                     filterSize = n;
                  }

                  j = p;
               }
               else if ( i->token == "col-vector" || i->token == "column-vector" )
               {
                  if ( filterType != SeparableFilterType )
                     PARSE_ERROR( "Invalid separable filter parameter", i );
                  if ( !colVector.IsEmpty() )
                     PARSE_ERROR( "Duplicate column vector specification", i );

                  token_list::const_iterator p = j;
                  colVector = SeparableFilter::coefficient_vector( n );
                  for ( SeparableFilter::coefficient* c = colVector.Begin(); c != colVector.End(); ++c, ++p )
                     *c = p->token.ToFloat();

                  if ( filterSize != 0 )
                  {
                     if ( filterSize != n )
                        PARSE_ERROR( "Incongruent separable column filter length; expected " + String( filterSize ) + " coefficients", j );
                  }
                  else
                  {
                     if ( n < 3 )
                        PARSE_ERROR( "Too few column filter coefficients specified - three or more coefficients are required", j );
                     if ( (n & 0x01) == 0 )
                        PARSE_ERROR( "Invalid even column filter length (" + String( n ) + ')', j );
                     filterSize = n;
                  }

                  j = p;
               }
               else
                  PARSE_ERROR( "Unknown filter parameter '" + i->token + '\'', i );

               int d = Distance( i, j );
               i = k;
               if ( d > 1 ) // j-i > 1 if and only if value is enclosed by brackets
                  ++i;
            }
         }
         break;

      default:
         PARSE_ERROR( "Internal parser error", i );
      }
   }

   if ( state != FilterTypeState )
      PARSE_ERROR( "Missing right bracket", tokens.At(tokens.UpperBound()));
}