[Insight-users] variogram / cancel update method

Glenn Pierce glennpierce at connectfree.co.uk
Sat Aug 28 11:06:07 EDT 2004


I would like to now submit my variogram code for inclusion.

I have included an example and a test case.

As I said before the code is quite CPU intensive, if anyone can see any
obvious optimisations I would be very interested.


Thanks

Glenn Pierce



On Tue, 2004-08-03 at 09:47 -0400, Luis Ibanez wrote:
> Hi Glenn,
> 
> The process for aborting is closely related to the Progress report
> and/or the Iteration report. When your filter is running (e.g. in
> the GenerateData() method. You should be invoking Progress events
> and/or Iteration events from time to time.
> 
> The GUI that listens to these events should offer the user a "Cancel"
> button where she/he can click in order to stop the execution of the
> filter. The Callback of such button just need to invoke in the ITK
> filter the method:
> 
>                filter->SetAbortGenerateData(true);
> 
> This will stop the execution of the filter.
> 
> Note that before attempting to run the pipeline again. You must
> invoke the method ResetPipeline() since many filters will be in
> the middle of their Update() process.
> 
> 
> Question:
> 
>     The Variogram code that you sent, is it intended as a contribution
>     to ITK, or just for the purpose of demonstrating the problem that
>     your are facing ?
> 
> 
> 
> Please let us know,
> 
> 
>     Thanks
> 
> 
> 
>          Luis
> 
> 
> 
> 
> ---------------------------------
> Glenn Pierce wrote:
> 
> > Hi
> > 
> > I have developed a variogram filter that still needs a bit of tidying
> > work. I have attached it.
> > 
> > This variogram is very processor intensive. 
> > In the worst case O(N^2), where N is the number of pixels of an image.
> > (In reality there are optimisations I have placed in means the
> > performance is quite a bit better than this). However for large images
> > it would still be slow. 
> > 
> > 
> > For my main project I am calling the update method of the variogram
> > filter in a separate thread, and wanted to allow users to cancel the
> > execution.
> > 
> > For this reason I wondered if there is an accepted way in ITK or any
> > examples to cancel the update method or in my case tell the variogram
> > filter to stop the loop in the update method ?
> > 
> > 
> > Thanks for the help
> > 
> > Glenn
> > 
> > 
> >
> 
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: itkVariogramTest.cxx
Type: text/x-c++src
Size: 2953 bytes
Desc: not available
Url : http://public.kitware.com/pipermail/insight-users/attachments/20040828/d84e7a22/itkVariogramTest.cxx
-------------- next part --------------
A non-text attachment was scrubbed...
Name: itkVariogramExample.cxx
Type: text/x-c++src
Size: 4442 bytes
Desc: not available
Url : http://public.kitware.com/pipermail/insight-users/attachments/20040828/d84e7a22/itkVariogramExample.cxx
-------------- next part --------------
A non-text attachment was scrubbed...
Name: itkImageToVariogram.h
Type: text/x-chdr
Size: 5581 bytes
Desc: not available
Url : http://public.kitware.com/pipermail/insight-users/attachments/20040828/d84e7a22/itkImageToVariogram.h
-------------- next part --------------
/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkImageToVariogram.txx,v $
  Language:  C++
  Date:      $Date: 2004/05/16 19:03:40 $
  Version:   $Revision: 1.1 $

  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 _itkImageToVariogram_txx
#define _itkImageToVariogram_txx

#include "itkProgressReporter.h"
#include "itkConstantBoundaryCondition.h"

namespace itk{ 
namespace Statistics{

template < class TImage >
ImageToVariogram< TImage >
::ImageToVariogram()
{
  this->semi_variance_maximum = 0;
  this->background_intensity = 0;
  this->has_background = false;
}

template < class TImage >
ImageToVariogram< TImage >
::~ImageToVariogram()
{
  delete lagContainer;
}

template < class TImage >
void
ImageToVariogram< TImage >
::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os,indent);
}

template < class TImage >
void
ImageToVariogram< TImage >
::SetImage(const TImage* image)
{
  m_Image = image ;

  // get spacing between data points
  spacing_x = m_Image->GetSpacing()[0];
  spacing_y = m_Image->GetSpacing()[1];

  // Set the max lag distance to use as one quater of the image diagonal
  this->max_lag = MaximumPossibleLag() / 4;

  IndexType index = m_Image->ComputeIndex( this->Size() - 1 );
  width = index[0];
  height = index[1];
}

/** returns the number of pixels in this container */
template < class TImage >
inline unsigned int
ImageToVariogram< TImage >
::Size() const
{
  return m_Image->GetPixelContainer()->Size() ;
}

/** returns the number of lags in this image */
template < class TImage >
unsigned int
ImageToVariogram< TImage >
::TotalLags()
{
  long unsigned int size = this->Size();
  // The sum of a arithmetrix series given by (number of terms) * (average of first and last terms)
  return ((size * (size - 1)) / 2);
}

/** returns the maximum lag in this image */
template < class TImage >
inline int
ImageToVariogram< TImage >
::MinimumLag()
{
  // Get the distance between the first and the next
  return this->CalculateLag(m_Image->ComputeIndex( 0 ), m_Image->ComputeIndex( 1 ));
}

/** returns the maximum lag in this image */
template < class TImage >
inline int
ImageToVariogram< TImage >
::MaximumPossibleLag()
{
  // Get the distance between the first and last pixel
  return static_cast<int>(this->CalculateLag(m_Image->ComputeIndex( 0 ),
    m_Image->ComputeIndex( this->Size() - 1 )));
}

/** Set the max lag that the variogram shall be calculated to
    The default is 1/4 of the maximum lag of the image diagonal */
template < class TImage >
inline void
ImageToVariogram< TImage >
::SetMaxLag(int lag)
{
  // Get the maximum lag distance to operate over
  if(lag > 0 && lag <= this->MaximumPossibleLag())
  {
    this->max_lag = lag;
  }
}

/** Set the background intensity that will be ignored */
template < class TImage >
inline void
ImageToVariogram< TImage >
::SetBackgroundIntensity(PixelType value)
{
  this->has_background = true;
  this->background_intensity = value;
}

template < class TImage >
void
ImageToVariogram< TImage >
::GenerateData()
{
  unsigned int size = this->Size();
  int lag;

  lagContainer = new LagDetail[this->max_lag + 1];

  // Create a progress reporter
  ProgressReporter progress(this, 0, size);

  ConstIteratorType mainPixelIter( m_Image, m_Image->GetRequestedRegion() );
  ConstIteratorType nextPixelIter( m_Image, m_Image->GetRequestedRegion() );

  IndexType nextPixelIndex;
  IndexType index;
  int max_x, min_x, max_y;

  for ( mainPixelIter.GoToBegin(); !mainPixelIter.IsAtEnd(); ++mainPixelIter)
   {
      IndexType currentPixelIndex = mainPixelIter.GetIndex();
      PixelType currentPixelValue = mainPixelIter.Get();

      if( (this->has_background == true) && (currentPixelValue == this->background_intensity) )
      {
        try
        {
          progress.CompletedPixel();
          continue;
        }
        catch( ProcessAborted & )
        {
          throw ProcessAborted(__FILE__,__LINE__);
          return;
        }
      }

      // Calculate the maximum and minumum pixels within the max lag circle
      // So we dont have to deal with all points
      max_x = currentPixelIndex[0] + this->max_lag;
      if(max_x > this->width)
      {
        max_x = this->width;
      }

      min_x = currentPixelIndex[0] - this->max_lag;
      if(min_x < 0)
      {
       min_x = 0;
      }

      // If the next pixel is further right than the max lag chosen move on to the next line
      max_y = currentPixelIndex[1] + this->max_lag;
      if(max_y > this->height)
      {
       max_y = this->height;
      }

      nextPixelIter = mainPixelIter;
      ++nextPixelIter;

      while (!nextPixelIter.IsAtEnd())
       {  
          nextPixelIndex = nextPixelIter.GetIndex();

          if( (this->has_background == true) && (nextPixelIter.Get() == this->background_intensity))
          {
            ++nextPixelIter;
            continue;
          }

          // If the next pixel is lower than the max lag chosen move on the current pixel
          if( nextPixelIndex[1] > max_y )
          {
            break;
          }

          // If the next pixel is further right than the max lag chosen move on to the next line
          if( ( nextPixelIndex[0] > max_x ) )
          {
            // move to next line
            index[0] = 0;
            index[1] = nextPixelIndex[1] + 1;

            nextPixelIter.SetIndex(index);
            nextPixelIndex = nextPixelIter.GetIndex();

            continue;
          }

          // If the next pixel is further left than the max lag chosen move on the 
          // first pixel within range.
          if( nextPixelIndex[0] < min_x )
          {
            // move to first pixel within reach
            index[0] = min_x;
            index[1] = nextPixelIndex[1];

            nextPixelIter.SetIndex(index);
            nextPixelIndex = nextPixelIter.GetIndex();

            continue;
          }

          lag = this->CalculateLag(currentPixelIndex, nextPixelIndex);
         
          // Check the pixel is within the max lag
          if (lag <= this->max_lag)
          {
              lagContainer[lag].count++;
              lagContainer[lag].sum_squared_diff += pow((currentPixelValue - nextPixelIter.Get()), 2);
          }

          ++nextPixelIter;
       }

       try
        {
          progress.CompletedPixel();
          continue;
        }
        catch( ProcessAborted & )
        {
          throw ProcessAborted(__FILE__,__LINE__);

          return;
        }
   }
}

template < class TImage >
inline double
ImageToVariogram< TImage >
::GetSemiVariance(int lag)
{
    if (lag > 0 && lag <= max_lag)
    {
      double tmp = lagContainer[lag].sum_squared_diff / (2.0 * lagContainer[lag].count);

      if(tmp > this->semi_variance_maximum)
       {
         this->semi_variance_maximum = tmp;
       }

      return tmp;
    }
    else
    {
      return -1.0;
    }
}

template < class TImage >
inline int
ImageToVariogram< TImage >
::CalculateLag(ImageToVariogram< TImage >::IndexType index1, ImageToVariogram< TImage >::IndexType index2)
{
  // Difference between pixels
  typename ImageToVariogram< TImage >::IndexType::IndexValueType x_pixel_difference = abs(index2[0] - index1[0]);
  typename ImageToVariogram< TImage >::IndexType::IndexValueType y_pixel_difference = abs(index2[1] - index1[1]);

  if(!y_pixel_difference)
    return x_pixel_difference;

  if(!x_pixel_difference)
    return y_pixel_difference;

  // Always round up
  int tmp = static_cast<int>(ceil(sqrt(pow(x_pixel_difference,2) + pow(y_pixel_difference,2))));

  return tmp;
}

} // end of namespace Statistics 
} // end of namespace itk

#endif


More information about the Insight-users mailing list