[Insight-developers] Use one algorithm or another in a filter, depending of the pixel type

Miller, James V (GE, Research) millerjv at crd.ge.com
Tue Mar 14 13:11:40 EST 2006


Gaetan, 

Your need for static_cast<> is essentially why we (really, Brad King) developed
the dispatch pattern.  Both cases of your "conditional" need to be compilable
regardless of the pixel type (regardless of the fact that both branches of the 
conditional will never be used).  This is fine for what you are doing.  When
branching on dimension, we couldn't use the "conditional" approach because
one branch would attempt to access memory out of bounds (for instance, 
access index[2] on a Index<2>).

If you wanted to used the overloading/dispatch approach in your case, you 
could do

struct DispatchBase{};
template <bool T> Dispatch : public DispatchBase {} ;

void AddPixel(DispatchBase, const TInputPixel &p);    // version for any type
void AddPixel(Dispatch<true>, const TInputPixel &p);  // version for integral types

and use the dispatch method

void AddPixel(const TInputPixel &p)
   {
   AddPixel(Dispatch<NumericTraits<TInputPixel>::is_integer>, p);
   }


-----Original Message-----
From: Gaetan Lehmann [mailto:gaetan.lehmann at jouy.inra.fr]
Sent: Monday, March 13, 2006 10:38 AM
To: Miller, James V (GE, Research); insight-developers at itk.org
Subject: Re: [Insight-developers] Use one algorithm or another in a
filter,depending of the pixel type



Jim,

I have used the following code to run the specialized version for some  
types:

   inline void AddPixel( const TInputPixel &p )
     {
     if( useVectorBasedAlgorithm() )
       { AddPixelVector( p ); }
     else
       { AddPixelMap( p ); }
     }

   inline bool useVectorBasedAlgorithm()
     {
     // bool, short and char are acceptable for vector based algorithm:  
they do not require
     // too much memory. Other types are not usable with that algorithm
     return typeid(TInputPixel) == typeid(unsigned char)
         || typeid(TInputPixel) == typeid(signed char)
         || typeid(TInputPixel) == typeid(unsigned short)
         || typeid(TInputPixel) == typeid(signed short)
         || typeid(TInputPixel) == typeid(bool);
     }

While it is less elegant than the overloaded implementation you proposed,  
it also let me easily specify a set of types usable with my specialized  
algorithm - I don't think it can be done easily with the overloaded  
implementation.
The bad point is that I had to do some static_cast in the code specialized  
for integer types to avoid warnings with real types - I guess that's not  
needed with overloaded implementation.

Anyway, that specialization give me an execution time about 4 times  
shorter better than with the general algorithm, which is very nice :-)

Gaetan

On Mon, 13 Mar 2006 15:17:14 +0100, Miller, James V (GE, Research)  
<millerjv at crd.ge.com> wrote:

> Gaetan,
>
> This can be done.  There is a certain pattern to follow that makes this  
> tractable.
> We call this a "dispatch" pattern.  Basically, you create a set of  
> overloaded functions.
> For instance, in itkMinMaxCurvatureFlowFunction, the dispatch pattern is  
> used to
> call either a 2D specific implementation, a 3D specific implementation,  
> or a general
> ND implementation. The same can be done for pixel types.  The pattern  
> creates
> a heirarchy of dispatch types so that the general case ends up calling an
> function overloaded on the root dispatch type.  Subclasses of the  
> dispatch
> type are used to provided overloaded functions for specific types.
>
> Here is the design from MinMaxCurvatureFlowFunction
>
>   struct DispatchBase {};
>   template<signed int VDimension>
>   struct Dispatch : DispatchBase {};
>  /** This method computes the threshold by averaging the intensity
>    *  in direction perpendicular to the image gradient. */
>   virtual PixelType ComputeThreshold( const Dispatch<2> &,
>                                       const NeighborhoodType &  
> neighborhood ) const;
>   virtual PixelType ComputeThreshold( const Dispatch<3> &,
>                                       const NeighborhoodType &  
> neighborhood ) const;
>   virtual PixelType ComputeThreshold( const DispatchBase &,
>                                       const NeighborhoodType &  
> neighborhood ) const;
>
> The appropriate function is called by the main entry point
>
>   threshold = this->ComputeThreshold( Dispatch<ImageDimension>(), it);
>
> This pattern will force only one of the overloaded functions to be  
> instantiated.  The
> same pattern can be used for pixel types (a DispatchBase class and a  
> Dispatch<short>, etc.).
>
> Jim
>
>
> -----Original Message-----
> From: insight-developers-bounces+millerjv=crd.ge.com at itk.org
> [mailto:insight-developers-bounces+millerjv=crd.ge.com at itk.org]On Behalf
> Of Gaetan Lehmann
> Sent: Sunday, March 12, 2006 10:21 AM
> To: insight-developers at itk.org
> Subject: [Insight-developers] Use one algorithm or another in a
> filter,depending of the pixel type
>
>
>
> Hi,
>
> Lots of algorithm can be implemented a lots more efficiently with some  
> pixels
> types - most of the time with char and short (signed or not).
> Is it possible automatically choose the algorithm used in a filter,  
> depending
> of the pixel type ?
> If yes, can it be done at build time ?
>
> Regards,
>
> Gaetan



-- 
Gaëtan Lehmann
Biologie du Développement et de la Reproduction
INRA de Jouy-en-Josas (France)
tel: +33 1 34 65 29 66    fax: 01 34 65 29 09
http://voxel.jouy.inra.fr


More information about the Insight-developers mailing list