KWHelloWorldExample-alex.cxx: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
No edit summary
No edit summary
Line 1: Line 1:
<pre><nowiki>#include "vtkKWApplication.h"
<pre><nowiki>#if defined(_MSC_VER)
#include "vtkKWWindowBase.h"
#pragma warning ( disable : 4786 )
#include "vtkKWLabel.h"
#endif
#include "vtkKWFrame.h"
#include "vtkKWRenderWidget.h"
#include "vtkKWHistogram.h"
#include "vtkKWPiecewiseFunctionEditor.h"


#include <vtksys/SystemTools.hxx>
#ifdef __BORLANDC__
#include <vtksys/CommandLineArguments.hxx>
#define ITK_LEAN_AND_MEAN
#endif


#include "itkImageToVTKImageFilter.h"
#include "itkImage.h"
#include "itkImage.h"
#include "itkGeodesicActiveContourLevelSetImageFilter.h"
#include "itkCurvatureAnisotropicDiffusionImageFilter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"


#include "vtkRenderer.h"
#include "vtkPiecewiseFunction.h"
#include "vtkVolumeProperty.h"
#include "vtkVolume.h"
#include "vtkVolumeRayCastCompositeFunction.h"
#include "vtkFixedPointVolumeRayCastMapper.h"
#include "vtkCamera.h"
#include "vtkPointData.h"


int my_main(int argc, char *argv[])
int main( int argc, char *argv[] )
{
{
   // Initialize Tcl
   if( argc < 12 )
 
  Tcl_Interp *interp = vtkKWApplication::InitializeTcl(argc, argv, &cerr);
  if (!interp)
     {
     {
     cerr << "Error: InitializeTcl failed" << endl ;
     std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputImageFile  outputImageFile";
    std::cerr << " Sigma SigmoidAlpha SigmoidBeta";
    std::cerr << " PropagationScaling CurvatureScaling";
    std::cerr << " AdvectionScaling maxRMSError maxIterations";
    std::cerr << " initialThreshold" << std::endl;
     return 1;
     return 1;
     }
     }


   // Load the Image via ITK
   // We define the image type using a particular pixel type and
  //  dimension. In this case the \code{float} type is used for the pixels
  //  due to the requirements of the smoothing filter.


   const unsigned int Dimension = 3;
  typedef  float            InternalPixelType;
   typedef unsigned char InputPixelType;
   const     unsigned char    Dimension = 3;
  typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
                                   
   typedef unsigned char OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
 
  //  This is the initial Threshold to determine the initial level set.
  typedef itk::BinaryThresholdImageFilter<
                        InternalImageType,
                        InternalImageType    >    ThresholdingFilterType2;
  ThresholdingFilterType2::Pointer inThresholder = ThresholdingFilterType2::New();
                       
  inThresholder->SetLowerThreshold( 0 );
  inThresholder->SetUpperThreshold( atoi(argv[11]) );
  inThresholder->SetOutsideValue(  0  );
  inThresholder->SetInsideValue(  255 );
 
  // Define the reader and writer.
  typedef  itk::ImageFileReader< InternalImageType > ReaderType;
  typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;


  typedef itk::Image<InputPixelType, Dimension> InputImageType;
  typedef itk::ImageFileReader<InputImageType> ReaderType;
   ReaderType::Pointer reader = ReaderType::New();
   ReaderType::Pointer reader = ReaderType::New();
//  reader->SetFileName( "/home/alex/interp/61457548-roi-8bit.tif" );
   WriterType::Pointer writer = WriterType::New();
   reader->SetFileName( "/home/alex/interp/61457548-roi-8bit-x4-ga-40-0.05-10-no_edges.tif" );


   try
   reader->SetFileName( argv[1] );
    {
  writer->SetFileName( argv[2] );
        reader->Update();
 
    }
   //  The RescaleIntensityImageFilter type is declared below. This filter will
   catch( itk::ExceptionObject & excep )
  //  renormalize image before sending them to writers.
    {
  typedef itk::RescaleIntensityImageFilter<
        std::cerr << "Exception while reading input!"<< std::endl;
                              InternalImageType,
        std::cerr << excep << std::endl;
                              OutputImageType >  CastFilterType;
    }
 
  //  The types of the
  //  GradientMagnitudeRecursiveGaussianImageFilter and
  //  SigmoidImageFilter are instantiated using the internal image
  //  type.
  //
  typedef  itk::GradientMagnitudeRecursiveGaussianImageFilter<  
                              InternalImageType,
                              InternalImageType >  GradientFilterType;
 
  GradientFilterType::Pointer  gradientMagnitude = GradientFilterType::New();
 
  //  The sigma of this Gaussian can be used to control
  //  the range of influence of the image edges. This filter has been discussed
  //  in Section~\ref{sec:GradientMagnitudeRecursiveGaussianImageFilter}
 
  const double sigma = atof( argv[3] );
  gradientMagnitude->SetSigma(  sigma  );
 
  typedef  itk::SigmoidImageFilter<                             
                              InternalImageType,
                              InternalImageType >  SigmoidFilterType;


   typedef itk::ImageToVTKImageFilter<InputImageType> FilterType;
   SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();
  FilterType::Pointer imtoimfilt = FilterType::New();
  imtoimfilt->SetInput( reader->GetOutput() );


   try
   //  The minimum and maximum values of the SigmoidImageFilter output
    {
  //  are defined with the methods \code{SetOutputMinimum()} and
            imtoimfilt->Update();
   //  \code{SetOutputMaximum()}. In our case, we want these two values to be
    }
  //  $0.0$ and $1.0$ respectively in order to get a nice speed image to feed
   catch( itk::ExceptionObject & except)
  //  the \code{FastMarchingImageFilter}. Additional details on the user of the
    {
  //  \doxygen{SigmoidImageFilter} are presented in
            std::cerr << "Exception while converting!"<< std::endl;
  //  section~\ref{sec:IntensityNonLinearMapping}.
            std::cerr << except << std::endl;
    }


   // Create transfer mapping scalar value to opacity
   sigmoid->SetOutputMinimum( 0.0 );
  vtkPiecewiseFunction *opacTransFunc = vtkPiecewiseFunction::New();
  sigmoid->SetOutputMaximum( 1.0 );
    opacTransFunc->AddPoint(0, 1.0);
    opacTransFunc->AddPoint(100, 0.0);
    opacTransFunc->AddPoint(255, 0.0);


   // The property describes how the data will look
   // The SigmoidImageFilter requires two parameters that define the linear
   vtkVolumeProperty *vp = vtkVolumeProperty::New();
   //  transformation to be applied to the sigmoid argument. This parameters
    vp->SetScalarOpacity(opacTransFunc);
  //  have been discussed in Sections~\ref{sec:IntensityNonLinearMapping} and
    vp->ShadeOn();
  //  \ref{sec:FastMarchingImageFilter}.
    vp->SetInterpolationTypeToLinear();


   vtkFixedPointVolumeRayCastMapper *rcm = vtkFixedPointVolumeRayCastMapper::New();
   const double alpha = atof( argv[4] );
    rcm->SetInput( imtoimfilt->GetOutput());
   const double beta  = atof( argv[5] );
  // The volume holds the mapper and the property and
  // can be used to position/orient the volume
   vtkVolume *volHead= vtkVolume::New();
  volHead->SetMapper(rcm);
  volHead->SetProperty(vp);


   // Create the application
  sigmoid->SetAlpha( alpha );
   // If --test was provided, ignore all registry settings, and exit silently
  sigmoid->SetBeta(  beta  );
   // Restore the settings that have been saved to the registry, like
 
   // the geometry of the user interface so far.
  typedef  itk::GeodesicActiveContourLevelSetImageFilter< InternalImageType,
                InternalImageType >    GeodesicActiveContourFilterType;
  GeodesicActiveContourFilterType::Pointer geodesicActiveContour =
                                    GeodesicActiveContourFilterType::New();
 
   // For the GeodesicActiveContourLevelSetImageFilter, scaling parameters
   // are used to trade off between the propagation (inflation), the
  //  curvature (smoothing) and the advection terms. These parameters are set
  //  using methods \code{SetPropagationScaling()},
  //  \code{SetCurvatureScaling()} and \code{SetAdvectionScaling()}. In this
   // example, we will set the curvature and advection scales to one and let
   // the propagation scale be a command-line argument.


   vtkKWApplication *app = vtkKWApplication::New();
   const double propagationScaling = atof( argv[6] );
   app->SetName("KWHelloWorldExample-alex");
   const double curvatureScaling = atof( argv[7] );
   app->RestoreApplicationSettingsFromRegistry();
   const double advectionScaling = atof( argv[8] );


   // Set a help link. Can be a remote link (URL), or a local file
   geodesicActiveContour->SetPropagationScaling( propagationScaling );
   // vtksys::SystemTools::GetFilenamePath(__FILE__) + "/help.html";
   geodesicActiveContour->SetCurvatureScaling( curvatureScaling );
   app->SetHelpDialogStartingPage("http://www.kwwidgets.org");
   geodesicActiveContour->SetAdvectionScaling( advectionScaling );


   // Add a window
   // Once activated the level set evolution will stop if the convergence
   // Set 'SupportHelp' to automatically add a menu entry for the help link
  //  criteria or if the maximum number of iterations is reached.  The
  //  convergence criteria is defined in terms of the root mean squared (RMS)
  //  change in the level set function. The evolution is said to have
  //  converged if the RMS change is below a user specified threshold.  In a
   // real application is desirable to couple the evolution of the zero set
  //  to a visualization module allowing the user to follow the evolution of
  //  the zero set. With this feedback, the user may decide when to stop the
  //  algorithm before the zero set leaks through the regions of low gradient
  //  in the contour of the anatomical structure to be segmented.
  //  !!!!!


   vtkKWWindowBase *win = vtkKWWindowBase::New();
   const double maxRMSError = atof( argv[9] );
   win->SupportHelpOn();
   const unsigned int maxIter = atoi( argv[10] );
   app->AddWindow(win);
   geodesicActiveContour->SetMaximumRMSError( maxRMSError );
   win->Create();
   geodesicActiveContour->SetNumberOfIterations( maxIter );


   vtkKWRenderWidget *hello_renderwidget = vtkKWRenderWidget::New();
   //  The following lines instantiate the thresholding filter that will
  hello_renderwidget->SetParent(win->GetViewFrame());
  //  process the final level set at the output of the
  hello_renderwidget->Create();
  //  GeodesicActiveContourLevelSetImageFilter.
  typedef itk::BinaryThresholdImageFilter<
                        InternalImageType,
                        OutputImageType    >   ThresholdingFilterType;
    
    
   vtkRenderer *hello_renderer = hello_renderwidget->GetRenderer();
   ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();
   hello_renderer->AddViewProp(volHead);  
                       
   hello_renderer->SetBackground(0.3, 0.6, 1.0);
   thresholder->SetLowerThreshold( -1000.0 );
   hello_renderer->GetActiveCamera()->ParallelProjectionOff();
   thresholder->SetUpperThreshold(     0.0 );
   hello_renderer->ResetCamera();
 
   thresholder->SetOutsideValue( );
   thresholder->SetInsideValue( 255 );
    
    
  app->Script("pack %s -side left -fill both -anchor c -expand y",
                  hello_renderwidget->GetWidgetName());
  hello_renderwidget->Delete();
 
// build an histogram of the data, it will be used inside the editor
// as if we were trying to tune a tfunc based on the real values
   
   
  vtkKWHistogram *pfed_hist = vtkKWHistogram::New();
   // Configure the pipeline.
  pfed_hist->BuildHistogram(
    imtoimfilt->GetOutput()->GetPointData()->GetScalars(), 0);
  double *range = pfed_hist->GetRange();
 
   // Assign our tfunc to the editor
  // Make sure we show the whole range of the tfunc
  // Use an histogram


   vtkKWPiecewiseFunctionEditor *pfed_tfunc2_editor =
   gradientMagnitude->SetInput( reader->GetOutput() );
    vtkKWPiecewiseFunctionEditor::New();
   sigmoid->SetInput( gradientMagnitude->GetOutput() );
  pfed_tfunc2_editor->SetParent(win->GetViewFrame());
   pfed_tfunc2_editor->Create();
  pfed_tfunc2_editor->SetBorderWidth(2);
  pfed_tfunc2_editor->SetReliefToGroove();
  pfed_tfunc2_editor->SetPadX(2);
  pfed_tfunc2_editor->SetPadY(2);
  pfed_tfunc2_editor->ExpandCanvasWidthOff();
  pfed_tfunc2_editor->SetCanvasWidth(250);
  pfed_tfunc2_editor->SetCanvasHeight(150);
  pfed_tfunc2_editor->SetLabelText("Opacity Function Editor");
  pfed_tfunc2_editor->SetBalloonHelpString(
    "Piecewise transfer function editor. Guidelines are dispayed "
    "for each midpoint, ticks are displayed in the "
    "parameter space at the bottom, the width is set explicitly. "
    "The range and histogram are based on a real image data.");


   pfed_tfunc2_editor->SetPiecewiseFunction(opacTransFunc);
   inThresholder->SetInput( reader->GetOutput() );
   pfed_tfunc2_editor->SetWholeParameterRangeToFunctionRange();
   geodesicActiveContour->SetInput(  inThresholder->GetOutput() );
   pfed_tfunc2_editor->SetVisibleParameterRangeToWholeParameterRange();
   geodesicActiveContour->SetFeatureImage( sigmoid->GetOutput() );


//  pfed_tfunc2_editor->PointIndexVisibilityOff();
  thresholder->SetInput( geodesicActiveContour->GetOutput() );
//  pfed_tfunc2_editor->SelectedPointIndexVisibilityOn();
   writer->SetInput( thresholder->GetOutput() );
//  pfed_tfunc2_editor->MidPointVisibilityOn();
//  pfed_tfunc2_editor->PointGuidelineVisibilityOff();
//  pfed_tfunc2_editor->MidPointGuidelineVisibilityOn();
//  pfed_tfunc2_editor->MidPointGuidelineValueVisibilityOn();
//  pfed_tfunc2_editor->SetMidPointGuidelineValueFormat("%-#6.0f");
//  pfed_tfunc2_editor->MidPointEntryVisibilityOn();
//  pfed_tfunc2_editor->SharpnessEntryVisibilityOn();
   pfed_tfunc2_editor->ValueRangeVisibilityOff();
  pfed_tfunc2_editor->ParameterRangeVisibilityOff();
  pfed_tfunc2_editor->SetLabelPositionToTop();
  pfed_tfunc2_editor->LockEndPointsParameterOn();


  pfed_tfunc2_editor->SetHistogram(pfed_hist);


   pfed_tfunc2_editor->ParameterTicksVisibilityOn();
   //  Here we configure all the writers required to see the intermediate
   pfed_tfunc2_editor->ComputeValueTicksFromHistogramOn();
  //  outputs of the pipeline. This is added here only for
//  pfed_tfunc2_editor->SetParameterTicksFormat(
  //  pedagogical/debugging purposes. These intermediate output are normaly not
//   pfed_tfunc2_editor->GetMidPointGuidelineValueFormat());
  //  required. Only the output of the final thresholding filter should be
   //  relevant.  Observing intermediate output is helpful in the process of
  //  fine tuning the parameters of filters in the pipeline.
  //
  CastFilterType::Pointer caster2 = CastFilterType::New();
  CastFilterType::Pointer caster3 = CastFilterType::New();
  CastFilterType::Pointer caster4 = CastFilterType::New();


   app->Script(
   WriterType::Pointer writer2 = WriterType::New();
    "pack %s -side top -anchor nw -expand n -padx 2 -pady 20",
   WriterType::Pointer writer3 = WriterType::New();
    pfed_tfunc2_editor->GetWidgetName());
   WriterType::Pointer writer4 = WriterType::New();
 
  pfed_tfunc2_editor->Delete();
   opacTransFunc->Delete();
   pfed_hist->Delete();


   /*
   caster2->SetInput( gradientMagnitude->GetOutput() );
  // Add a label, attach it to the view frame, and pack
   writer2->SetInput( caster2->GetOutput() );
 
   writer2->SetFileName("GeodesicActiveContourImageFilterOutput-grad.tif");
  vtkKWLabel *hello_label = vtkKWLabel::New();
   caster2->SetOutputMinimum(   0 );
   hello_label->SetParent(win->GetViewFrame());
   caster2->SetOutputMaximum( 255 );
   hello_label->Create();
  writer2->Update();
   hello_label->SetText("Hello, World!");
  caster2->ReleaseDataFlagOn();
   app->Script("pack %s -side left -anchor c -expand y",
   writer2->ReleaseDataFlagOn();
              hello_label->GetWidgetName());
   hello_label->Delete();
*/
    
    
   // Start the application
  caster3->SetInput( sigmoid->GetOutput() );
   // If --test was provided, do not enter the event loop and run this example
  writer3->SetInput( caster3->GetOutput() );
   // as a non-interactive test for software quality purposes.
  writer3->SetFileName("GeodesicActiveContourImageFilterOutput-sigmoid.tif");
  caster3->SetOutputMinimum(  0 );
  caster3->SetOutputMaximum( 255 );
  writer3->Update();
  caster3->ReleaseDataFlagOn();
  writer3->ReleaseDataFlagOn();
   
  caster4->SetInput( inThresholder->GetOutput() );
  writer4->SetInput( caster4->GetOutput() );
  writer4->SetFileName("GeodesicActiveContourImageFilterOutput-inThresh.tif");
  caster4->SetOutputMinimum(  0 );
  caster4->SetOutputMaximum( 255 );
  writer4->Update();
  caster4->ReleaseDataFlagOn();
  writer4->ReleaseDataFlagOn();
   
   // Software Guide : BeginLatex
  // 
  //  The invocation of the \code{Update()} method on the writer triggers the
   // execution of the pipeline.  As usual, the call is placed in a
   // \code{try/catch} block should any errors occur or exceptions be thrown.
  //
  //  Software Guide : EndLatex


   int ret = 0;
   // Software Guide : BeginCodeSnippet
   win->Display();
   try
   app->Start(argc, argv);
    {
  ret = app->GetExitStatus();
    writer->Update();
   win->Close();
    }
   catch(itk::ExceptionObject & excep)
    {
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    }
   // Software Guide : EndCodeSnippet


   // Deallocate and exit
   // Print out some useful information
  std::cout << std::endl;
  std::cout << "Max. no. iterations: " << geodesicActiveContour->GetNumberOfIterations() << std::endl;
  std::cout << "Max. RMS error: " << geodesicActiveContour->GetMaximumRMSError() << std::endl;
  std::cout << std::endl;
  std::cout << "No. elapsed iterations: " << geodesicActiveContour->GetElapsedIterations() << std::endl;
  std::cout << "RMS change: " << geodesicActiveContour->GetRMSChange() << std::endl;


  win->Delete();
   return 0;
  app->Delete();
 
   return ret;
}
}


#if defined(_WIN32) && !defined(__CYGWIN__)
</nowiki></pre>
#include <windows.h>
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int)
{
  int argc;
  char **argv;
  vtksys::SystemTools::ConvertWindowsCommandLineToUnixArguments(
    lpCmdLine, &argc, &argv);
  int ret = my_main(argc, argv);
  for (int i = 0; i < argc; i++) { delete [] argv[i]; }
  delete [] argv;
  return ret;
}
#else
int main(int argc, char *argv[])
{
  return my_main(argc, argv);
}
#endif</nowiki></pre>


{{CompleteSetup/Template/Footer}}
{{CompleteSetup/Template/Footer}}

Revision as of 16:40, 5 May 2006

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "itkImage.h"
#include "itkGeodesicActiveContourLevelSetImageFilter.h"
#include "itkCurvatureAnisotropicDiffusionImageFilter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"


int main( int argc, char *argv[] )
{
  if( argc < 12 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputImageFile  outputImageFile";
    std::cerr << " Sigma SigmoidAlpha SigmoidBeta";
    std::cerr << " PropagationScaling CurvatureScaling";
    std::cerr << " AdvectionScaling maxRMSError maxIterations"; 
    std::cerr << " initialThreshold" << std::endl;
    return 1;
    }

  //  We define the image type using a particular pixel type and
  //  dimension. In this case the \code{float} type is used for the pixels
  //  due to the requirements of the smoothing filter.

  typedef   float            InternalPixelType;
  const     unsigned char    Dimension = 3;
  typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;
                                     
  typedef unsigned char OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  
  //  This is the initial Threshold to determine the initial level set.
  typedef itk::BinaryThresholdImageFilter< 
                        InternalImageType, 
                        InternalImageType    >    ThresholdingFilterType2;
  ThresholdingFilterType2::Pointer inThresholder = ThresholdingFilterType2::New();
                        
  inThresholder->SetLowerThreshold( 0 );
  inThresholder->SetUpperThreshold( atoi(argv[11]) );
  inThresholder->SetOutsideValue(  0  );
  inThresholder->SetInsideValue(  255 );

  // Define the reader and writer.
  typedef  itk::ImageFileReader< InternalImageType > ReaderType;
  typedef  itk::ImageFileWriter<  OutputImageType  > WriterType;

  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  reader->SetFileName( argv[1] );
  writer->SetFileName( argv[2] );

  //  The RescaleIntensityImageFilter type is declared below. This filter will
  //  renormalize image before sending them to writers.
  typedef itk::RescaleIntensityImageFilter< 
                               InternalImageType, 
                               OutputImageType >   CastFilterType;

  //  The types of the
  //  GradientMagnitudeRecursiveGaussianImageFilter and
  //  SigmoidImageFilter are instantiated using the internal image
  //  type.
  //
  typedef   itk::GradientMagnitudeRecursiveGaussianImageFilter< 
                               InternalImageType, 
                               InternalImageType >  GradientFilterType;

  GradientFilterType::Pointer  gradientMagnitude = GradientFilterType::New();
  
  //  The sigma of this Gaussian can be used to control
  //  the range of influence of the image edges. This filter has been discussed
  //  in Section~\ref{sec:GradientMagnitudeRecursiveGaussianImageFilter}

  const double sigma = atof( argv[3] );
  gradientMagnitude->SetSigma(  sigma  );
  
  typedef   itk::SigmoidImageFilter<                               
                               InternalImageType, 
                               InternalImageType >  SigmoidFilterType;

  SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();

  //  The minimum and maximum values of the SigmoidImageFilter output
  //  are defined with the methods \code{SetOutputMinimum()} and
  //  \code{SetOutputMaximum()}. In our case, we want these two values to be
  //  $0.0$ and $1.0$ respectively in order to get a nice speed image to feed
  //  the \code{FastMarchingImageFilter}. Additional details on the user of the
  //  \doxygen{SigmoidImageFilter} are presented in
  //  section~\ref{sec:IntensityNonLinearMapping}.

  sigmoid->SetOutputMinimum(  0.0  );
  sigmoid->SetOutputMaximum(  1.0  );

  //  The SigmoidImageFilter requires two parameters that define the linear
  //  transformation to be applied to the sigmoid argument. This parameters
  //  have been discussed in Sections~\ref{sec:IntensityNonLinearMapping} and
  //  \ref{sec:FastMarchingImageFilter}.

  const double alpha =  atof( argv[4] );
  const double beta  =  atof( argv[5] );

  sigmoid->SetAlpha( alpha );
  sigmoid->SetBeta(  beta  );
  
  typedef  itk::GeodesicActiveContourLevelSetImageFilter< InternalImageType, 
                InternalImageType >    GeodesicActiveContourFilterType;
  GeodesicActiveContourFilterType::Pointer geodesicActiveContour = 
                                     GeodesicActiveContourFilterType::New();
  
  //  For the GeodesicActiveContourLevelSetImageFilter, scaling parameters
  //  are used to trade off between the propagation (inflation), the
  //  curvature (smoothing) and the advection terms. These parameters are set
  //  using methods \code{SetPropagationScaling()},
  //  \code{SetCurvatureScaling()} and \code{SetAdvectionScaling()}. In this
  //  example, we will set the curvature and advection scales to one and let
  //  the propagation scale be a command-line argument.

  const double propagationScaling = atof( argv[6] );
  const double curvatureScaling = atof( argv[7] );
  const double advectionScaling = atof( argv[8] );

  geodesicActiveContour->SetPropagationScaling( propagationScaling );
  geodesicActiveContour->SetCurvatureScaling( curvatureScaling );
  geodesicActiveContour->SetAdvectionScaling( advectionScaling );

  //  Once activated the level set evolution will stop if the convergence
  //  criteria or if the maximum number of iterations is reached.  The
  //  convergence criteria is defined in terms of the root mean squared (RMS)
  //  change in the level set function. The evolution is said to have
  //  converged if the RMS change is below a user specified threshold.  In a
  //  real application is desirable to couple the evolution of the zero set
  //  to a visualization module allowing the user to follow the evolution of
  //  the zero set. With this feedback, the user may decide when to stop the
  //  algorithm before the zero set leaks through the regions of low gradient
  //  in the contour of the anatomical structure to be segmented.
  //  !!!!!

  const double maxRMSError = atof( argv[9] );
  const unsigned int maxIter = atoi( argv[10] );
  geodesicActiveContour->SetMaximumRMSError( maxRMSError );
  geodesicActiveContour->SetNumberOfIterations( maxIter );

  //  The following lines instantiate the thresholding filter that will
  //  process the final level set at the output of the
  //  GeodesicActiveContourLevelSetImageFilter.
  typedef itk::BinaryThresholdImageFilter< 
                        InternalImageType, 
                        OutputImageType    >    ThresholdingFilterType;
  
  ThresholdingFilterType::Pointer thresholder = ThresholdingFilterType::New();
                        
  thresholder->SetLowerThreshold( -1000.0 );
  thresholder->SetUpperThreshold(     0.0 );

  thresholder->SetOutsideValue(  0  );
  thresholder->SetInsideValue(  255 );
  
 
  // Configure the pipeline.

  gradientMagnitude->SetInput( reader->GetOutput() );
  sigmoid->SetInput( gradientMagnitude->GetOutput() );

  inThresholder->SetInput( reader->GetOutput() );
  geodesicActiveContour->SetInput(  inThresholder->GetOutput() );
  geodesicActiveContour->SetFeatureImage( sigmoid->GetOutput() );

  thresholder->SetInput( geodesicActiveContour->GetOutput() );
  writer->SetInput( thresholder->GetOutput() );


  //  Here we configure all the writers required to see the intermediate
  //  outputs of the pipeline. This is added here only for
  //  pedagogical/debugging purposes. These intermediate output are normaly not
  //  required. Only the output of the final thresholding filter should be
  //  relevant.  Observing intermediate output is helpful in the process of
  //  fine tuning the parameters of filters in the pipeline. 
  //
  CastFilterType::Pointer caster2 = CastFilterType::New();
  CastFilterType::Pointer caster3 = CastFilterType::New();
  CastFilterType::Pointer caster4 = CastFilterType::New();

  WriterType::Pointer writer2 = WriterType::New();
  WriterType::Pointer writer3 = WriterType::New();
  WriterType::Pointer writer4 = WriterType::New();

  caster2->SetInput( gradientMagnitude->GetOutput() );
  writer2->SetInput( caster2->GetOutput() );
  writer2->SetFileName("GeodesicActiveContourImageFilterOutput-grad.tif");
  caster2->SetOutputMinimum(   0 );
  caster2->SetOutputMaximum( 255 );
  writer2->Update();
  caster2->ReleaseDataFlagOn();
  writer2->ReleaseDataFlagOn();
  
  caster3->SetInput( sigmoid->GetOutput() );
  writer3->SetInput( caster3->GetOutput() );
  writer3->SetFileName("GeodesicActiveContourImageFilterOutput-sigmoid.tif");
  caster3->SetOutputMinimum(   0 );
  caster3->SetOutputMaximum( 255 );
  writer3->Update();
  caster3->ReleaseDataFlagOn();
  writer3->ReleaseDataFlagOn();
    
  caster4->SetInput( inThresholder->GetOutput() );
  writer4->SetInput( caster4->GetOutput() );
  writer4->SetFileName("GeodesicActiveContourImageFilterOutput-inThresh.tif");
  caster4->SetOutputMinimum(   0 );
  caster4->SetOutputMaximum( 255 );
  writer4->Update();
  caster4->ReleaseDataFlagOn();
  writer4->ReleaseDataFlagOn();
    
  //  Software Guide : BeginLatex
  //  
  //  The invocation of the \code{Update()} method on the writer triggers the
  //  execution of the pipeline.  As usual, the call is placed in a
  //  \code{try/catch} block should any errors occur or exceptions be thrown.
  //
  //  Software Guide : EndLatex 

  // Software Guide : BeginCodeSnippet
  try
    {
    writer->Update();
    }
  catch(itk::ExceptionObject & excep)
    {
    std::cerr << "Exception caught !" << std::endl;
    std::cerr << excep << std::endl;
    }
  // Software Guide : EndCodeSnippet

  // Print out some useful information 
  std::cout << std::endl;
  std::cout << "Max. no. iterations: " << geodesicActiveContour->GetNumberOfIterations() << std::endl;
  std::cout << "Max. RMS error: " << geodesicActiveContour->GetMaximumRMSError() << std::endl;
  std::cout << std::endl;
  std::cout << "No. elapsed iterations: " << geodesicActiveContour->GetElapsedIterations() << std::endl;
  std::cout << "RMS change: " << geodesicActiveContour->GetRMSChange() << std::endl;

  return 0;
}



Complete Setup: [Welcome | Site Map]