[Insight-developers] Operators with explicitly specified coefficients

Gunnar Farnebäck gunnar at bwh.harvard.edu
Thu Jul 8 17:18:36 EDT 2004


> But I think it makes to have an operator that does this.  Perhaps one
> that is not limited to directional kernels as well.

I wouldn't mind a more general one as well, but I'm not sure it really
makes sense to have them in the same class. In any case I'm not enough
up to speed with C++ and ITK to design that.

> As for ITK style issues, here are a few minor points:
> 
> 1. The ITK style limits abbreviations to just a few abbreviations in 
> widespread acceptance.  So the methods Set/GetCoeffs() should be written
> out as SetCoefficients()/GetCoefficients().

Fixed.

> 2. You probably need a default constructor that will initialize the 
> direction ivar and fill the coefficient vector with good default values
> (maybe 1 at the center pixel and zeros elsewhere).

I chose 0 at the center pixel and no coefficients elsewhere
(technically speaking). This way it should be obvious if one forgets
to set own values, getting all zero output rather than a copy of the
input. I hope this isn't inconsistent with any ITK philosophy.

> 3. DirectionalOperator(int direction) and DirectionalOperator(int direction,
> const std::vector<double> coeffs) - I am not sure about having these two 
> additional constructors.  I don't think the other operators have
> constructors
> that take "direction" as an argument.  So to be consistent, this operator
> should probably only have the default constructor and the copy constructor.
> Users can use the SetDirection() and SetCoefficients() methods to populate
> the operator.

Actually I'd prefer to only allow setting direction and coefficients
directly from a constructor, but of course consistency is more
important. I've removed these.

Is there any design document which discusses for example use of
constructors?

I also removed the internal calls to CreateDirectional(), to be more
consistent with other operators.

> 4. ITK style is to preface calls to member functions with "this->", so
> instead
> of 
> 	SetDirection(direction);
> 
> we use
> 
> 	this->SetDirection(direction);

Fixed.

> 5. You have a duplication of "data".  The coefficient vector is stored in 
> an ivar and then again in the neighborhood.  You might want to look at 
> trying to eliminate your ivar to hold the coefficient vector and just have
> the coefficients stored in the neighborhood.

I've looked but failed to find any attractive way to eliminate it. I'm
open for suggestions if it's obvious to somebody else how to do it.

Take two of itkDirectionalOperator.h is attached. Is the name of the
class appropriate or should it be named something else?

I also have some minor and obvious bugfixes (mostly documentation) for
GaussianOperator and NeighborhoodOperator. Should I send patches to
this list or directly to some developer, if so who?

/Gunnar
-------------- next part --------------
/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkDirectionalOperator.h,v $
  Language:  C++
  Date:      $Date: 2003/09/10 14:29:09 $
  Version:   $Revision: 1.22 $

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __itkDirectionalOperator_h
#define __itkDirectionalOperator_h

#include "itkNeighborhoodOperator.h"
namespace itk {

/**
 * \class DirectionalOperator
 * \brief A NeighborhoodOperator for one dimensional directional
 * kernels with explicitly specified coefficients.
 *
 * DirectionalOperator can be used to perform directional filtering
 * by taking its inner product with a Neighborhood
 * (NeighborhoodIterator) that is swept across an image region.
 *
 * DirectionalOperator takes two parameters:
 *
 * (1) The direction of the operator.
 *
 * (2) The coefficients of the filter.
 *
 * After setting the parameters it is necessary to call the
 * CreateDirectional() method, before the operator can be used.
 *
 * \sa NeighborhoodOperator
 * \sa NeighborhoodIterator
 * \sa Neighborhood
 *
 * \ingroup Operators
 */
template<class TPixel, unsigned int VDimension = 2,
         class TAllocator = NeighborhoodAllocator<TPixel> >
class ITK_EXPORT DirectionalOperator
  : public NeighborhoodOperator<TPixel, VDimension, TAllocator>
{
public:
  /** Standard class typedefs. */
  typedef DirectionalOperator Self;
  typedef NeighborhoodOperator<TPixel, VDimension, TAllocator>  Superclass;
  
  /** Constructor. */
  DirectionalOperator()
  {
    m_Coefficients = std::vector<double>(1, 0.0);
  }
  
  /** Copy constructor. */
  DirectionalOperator(const Self &other)
    : NeighborhoodOperator<TPixel, VDimension, TAllocator>(other)
  {
    m_Coefficients = other.m_Coefficients;
  }

  /** Assignment operator. */
  Self &operator=(const Self &other)
  {
    Superclass::operator=(other);
    m_Coefficients = other.m_Coefficients;
    return *this;
  }
  
  /** Sets the kernel coefficients. */
  void SetCoefficients(const std::vector<double> coefficients)
  {
    m_Coefficients = coefficients;
  }

  /** Returns the kernel coefficients. */
  std::vector<double> GetCoefficients() const
  {
    return m_Coefficients;
  }
  
  /** Prints some debugging information. */
  void PrintSelf(std::ostream &os, Indent i) const
  {
    os << i << "DirectionalOperator { this=" << this
       << ", m_Coefficients =";
    for (int k = 0; k < m_Coefficients.size(); k++)
      os << " " << m_Coefficients[k];
    os << "} " << std::endl;
    Superclass::PrintSelf(os, i.GetNextIndent());
  }
  
protected:
  typedef typename Superclass::CoefficientVector CoefficientVector;

  /** Calculates operator coefficients. */
  CoefficientVector GenerateCoefficients()
  {
    return m_Coefficients;
  }

  /** Arranges coefficients spatially in the memory buffer. */
  void Fill(const CoefficientVector& coeff)
  {
    this->FillCenteredDirectional(coeff);
  }

private:
  /** Filter coefficients. */
  CoefficientVector m_Coefficients;
  
  /** For compatibility with itkWarningMacro. */
  const char *GetNameOfClass()
  {
    return "itkDirectionalOperator";
  }
  
};

} // namespace itk


#ifndef ITK_MANUAL_INSTANTIATION
#endif

#endif


More information about the Insight-developers mailing list