Author Topic: PCL Linear Filter is not circular/ does not recognize it is separable  (Read 2902 times)

Offline georg.viehoever

  • PTeam Member
  • PixInsight Jedi Master
  • ******
  • Posts: 2132
Hi Juan,

in http://pixinsight.com/forum/index.php?topic=3289.msg22630#msg22630, you said "Nope. LinearFilter used that way defines a circular filter with constant value equal to one". Here are the coeffcients of a LinearFilter created by LinearFilter filter(3,1.0/9,1.0/9):

Code: [Select]
LinearFilterCoefficients 0.111111,0.111111,0.111111,0.111111,0.111111,0.111111,0.111111,0.111111,0.111111,
Code used for output:
Code: [Select]
    std::cout<<"LinearFilterCoefficients ";
    for (const float *val=filter.Begin();val!=filter.End();++val){
      std::cout<<*val<<",";
    }
    std::cout<<std::endl;

To me, this looks like a 3x3 box filter that should be separable (or am I getting something wrong here?).

Georg
Georg (6 inch Newton, unmodified Canon EOS40D+80D, unguided EQ5 mount)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Touché. Revising LinearFilter implementation (pcl/LinearFilter.h from line # 183 to line # 196) it is clear that LinearFilter cannot generate a circular filter:

Code: [Select]
   void Initialize( float v0, float v1 )
   {
      centralValue = v0;
      outerValue = v1;
      float* h = *coefficients;
      if ( h != 0 )
      {
         int n2 = Size() >> 1;
         float dvn2 = (v1 - v0)/n2;
         for ( int y = -n2; y <= n2; ++y )
            for ( int x = -n2; x <= n2; ++x )
               *h++ = v0 + Sqrt( float( x*x + y*y ) ) * dvn2;
      }
   }

(which, by the way, is a naive, shamelessly unoptimized implementation).

It generates a 2D distribution with central radial symmetry, but in the degenerate case centralValue = outerValue it yields a box average filter, as you correctly understood.

So the bug is actually in my assertion, not in the code that generates a LinearFilter instance. Next time I better read my own documentation before judging your use of PCL classes :)

Now the problem with separability, or more precisely, with evaluation of separability. I guess the problem here is with the default tolerance value (1e-6). Instead of calling KernelFilter::IsSeparable() and/or KernelFilter::AsSeparableFilter(), try specifying a moderate tolerance value; for example:

LinearFilter filter( 3, 1.0/9, 1.0/9 );
SeparableFilter separable = filter.AsSeparableFilter( 5.0e-06 ); // explicit tolerance value
if ( separable.IsEmpty() )
   throw Error( "A box average filter should be identified as separable!" );

Let me know if it works. Anyway, this is now of 'academic' interest only since you can build and use separable filters directly, as I explained in the thread in question (and implemented in your code).

In the next PCL version I'll try to fix these problems by computing an automatic tolerance, based on the singular value decomposition performed to compute separable filter coefficients. Thanks for looking deeply into this.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/