[Insight-users] watershed segmentation without RGB?

Luis Ibanez luis.ibanez at kitware.com
Fri, 30 Apr 2004 16:27:15 -0400


Hi Laurent,

It is likely that the error you are getting is due to
the interconnections between the ITK and VTK pipelines
and not to the use of the Watershed filter itself.

Please do the following:


A) Take a look at the python example:

    Insight/Examples/Segmentation/
               WatershedSegmentation1.py

    This example is taking a graylevel image as input.
    Python code looks pretty much like C++, just replace
    all the "." with "->" and add ";" at the end     :-)



B) Just to double-check
    In your program, replace the Watershed image filter
    with an inocuous filter such as the MedianImageFitler.
    Recompile and rerun your program.  If you still get
    the abnormal termination error, at least you rule out
    the Watershed filter as the culprit.



C) You are now 'manually' connecting ITK and VTK pipelines.
    This is tricky and it is easy to get it wrong.

    For your convenience, filters have been made available
    in InsightApplications that will connect the two pipelines
    in a single operation.  Please use the filters:

    InsightApplications/Auxiliary/vtk
                   itkImageToVTKImageFilter.h
                   itkImageToVTKImageFilter.txx
                   itkVTKImageToImageFilter.h
                   itkVTKImageToImageFilter.txx


Regards,


    Luis


--------------------------
Laurent Mundeleer wrote:

> Hi James,
> 
> I've tried to convert the WatershedSegmentation1.cxx to grayscale 
> images, but I still have problems (abnormal termination).
> Here's my code :
> --------------------
> tumorFilterITK.h
> --------------------
> #ifndef tumorFilterITK_H
> #define tumorFilterITK_H
> 
> 
> #include <itkVTKImageExport.h>
> #include <itkVTKImageImport.h>
> #include <vtkImageImport.h>
> #include <vtkImageExport.h>
> 
> #include <itkGradientAnisotropicDiffusionImageFilter.h>
> #include <itkGradientMagnitudeImageFilter.h>
> #include <itkWatershedImageFilter.h>
> #include <itkCastImageFilter.h>
> 
> class tumorFilterITK
> {
> 
> public:
> 
>    typedef short pixelType;
> 
>    typedef itk::Image<pixelType, 3> ImageType;
>    typedef itk::Image<unsigned long, 3> ImageTypeOut;
> 
>    typedef itk::VTKImageImport<ImageType> ImageImportType;
>    typedef itk::VTKImageExport<ImageType> ImageExportType;
> 
>    typedef itk::CastImageFilter<ImageTypeOut, ImageType> CastFilterType;
> 
>    typedef itk::GradientAnisotropicDiffusionImageFilter<ImageType,    
> ImageType>  DiffusionFilterType;
>    typedef itk::GradientMagnitudeImageFilter<ImageType, ImageType> 
> GradientMagnitudeFilterType;
>    typedef itk::WatershedImageFilter<ImageType> WatershedFilterType;
> 
>    tumorFilterITK(vtkImageImport*, vtkImageExport*);
>    void tumorFilterITKExec();
> 
> private:
> 
>    ImageImportType::Pointer itkImporter;
>    ImageExportType::Pointer itkExporter;
> 
>    CastFilterType::Pointer caster;
> 
>    DiffusionFilterType::Pointer diffusion;
>    GradientMagnitudeFilterType::Pointer gradient;
>    WatershedFilterType::Pointer watershed;
> };
> 
> #endif
> --------------------------------------------
> --------------------
> tumorFilterITK.cpp
> --------------------
> 
> #include "tumorFilterITK.h"
> 
> /// connexion de ITK a VTK
> template <typename ITK_Exporter, typename VTK_Importer>
> void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
> {
>  
> importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); 
> 
>  
> importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); 
> 
>  importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
>  importer->SetSpacingCallback(exporter->GetSpacingCallback());
>  importer->SetOriginCallback(exporter->GetOriginCallback());
>  importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
>  
> importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); 
> 
>  
> importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); 
> 
>  importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
>  importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
>  importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
>  importer->SetCallbackUserData(exporter->GetCallbackUserData());
> }
> 
> //-----------------------------------------------------------------
> 
> /// connexion de VTK a ITK
> template <typename VTK_Exporter, typename ITK_Importer>
> void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
> {
>  
> importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); 
> 
>  
> importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); 
> 
>  importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
>  importer->SetSpacingCallback(exporter->GetSpacingCallback());
>  importer->SetOriginCallback(exporter->GetOriginCallback());
>  importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
>  
> importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); 
> 
>  
> importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); 
> 
>  importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
>  importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
>  importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
>  importer->SetCallbackUserData(exporter->GetCallbackUserData());
> }
> 
> //-----------------------------------------------------------------
> 
> ///contructeur initialisant le pipeline ITK
> tumorFilterITK::tumorFilterITK(vtkImageImport* vtkImporter, 
> vtkImageExport *vtkExporter)
> {          itkImporter = ImageImportType::New();
>    itkExporter = ImageExportType::New();
> 
> //    itkExporter->SetInput(itkImporter->GetOutput());
>    diffusion = DiffusionFilterType::New();
>    gradient = GradientMagnitudeFilterType::New();
>    caster = CastFilterType::New();
> 
>    watershed = WatershedFilterType::New();
>      ConnectPipelines(vtkExporter, itkImporter);
>    ConnectPipelines(itkExporter, vtkImporter);  
>    tumorFilterITKExec();
> }
> 
> //-----------------------------------------------------------------
> 
> /// execution du filtre de detection de tumeurs
> void tumorFilterITK::tumorFilterITKExec()
> {
> 
>     //inputImage outputImage conductanceTerm diffusionIterations 
> lowerThreshold outputScaleLevel gradientMode " << std::endl;
> 
>    diffusion->SetNumberOfIterations( 5 ); // 5 typically
>    diffusion->SetConductanceParameter( 3.0 ); // 3.0 typically
>    diffusion->SetTimeStep(0.125);
> 
>    watershed->SetLevel( 0.001 ); // 0->1 en %
>    watershed->SetThreshold( 0.001 ); // 0->1 en %
> 
>    diffusion->SetInput(itkImporter->GetOutput());
>    gradient->SetInput(diffusion->GetOutput());
>    watershed->SetInput(gradient->GetOutput());
> 
>    try
>    {
>    watershed->Update();
>    }
>    catch (itk::ExceptionObject &e)
>    {
>    std::cerr << e << std::endl;
>    }
>    caster->SetInput(watershed->GetOutput());
>    itkExporter->SetInput(caster->GetOutput());
> }
> 
> ------------------------------------
> 
> Maybe can you help me?
> Thanks again,
> 
> Regards,
> 
> Laurent
> 
> 
> 
> Miller, James V (Research) wrote:
> 
>> Watershed can be run on grayscale images.  The example
>> (WatershedSegmentation1.cxx) is set up to process RGB pixels. But you can
>> easily run watershed on a grayscale image.
>>
>> You'll want to create a similar program to WatershedSegmentation1.cxx 
>> that
>> reads a scalar image, produces a gradient magnitude image
>> (GradientMagnitudeImageFilter or 
>> RecursiveGradientMagnitudeImageFilter), and
>> runs watershed on the gradient magnitude image.
>>
>> So you just need to change the pixel type, delete the word "Vector" 
>> from any
>> class type in example, and change the CastType to a CastImageFilter that
>> converts a scalar image into an image of floating point pixels 
>> (alternative,
>> you can remove the cast filter altogether and have the reader return an
>> image of floating point pixels.  Here is a quick stab at it (haven't 
>> tried
>> to compile it....)
>>
>> #ifdef _MSC_VER
>> #pragma warning ( disable : 4786 )
>> #endif
>>
>> #include <iostream>
>>
>> #include "itkGradientAnisotropicDiffusionImageFilter.h"
>> #include "itkGradientMagnitudeImageFilter.h"
>> #include "itkWatershedImageFilter.h"
>>
>> #include "itkImageFileReader.h"
>> #include "itkImageFileWriter.h"
>> #include "itkUnaryFunctorImageFilter.h"
>> #include "itkScalarToRGBPixelFunctor.h"
>>
>> int main( int argc, char *argv[] )
>> {
>>  if (argc < 8 )
>>    {
>>    std::cerr << "Missing Parameters " << std::endl;
>>    std::cerr << "Usage: " << argv[0];
>>    std::cerr << " inputImage outputImage conductanceTerm
>> diffusionIterations lowerThreshold outputScaleLevel gradientMode " <<
>> std::endl;
>>    return 1;
>>    }
>>  
>>  typedef itk::RGBPixel<unsigned char>   RGBPixelType;
>>  typedef itk::Image<RGBPixelType, 2>    RGBImageType;
>>  typedef itk::Image<unsigned long, 2>   LabeledImageType;
>>  typedef itk::Image<float, 2>           ScalarImageType;
>>
>>  typedef itk::ImageFileReader<ScalarImageType> FileReaderType;
>>  typedef itk::GradientAnisotropicDiffusionImageFilter<ScalarImageType,
>>    ScalarImageType>  DiffusionFilterType;
>>  typedef itk::GradientMagnitudeImageFilter<ScalarImageType>
>>    ScalarMagnitudeFilterType;  typedef 
>> itk::WatershedImageFilter<ScalarImageType> WatershedFilterType;
>>  // Software Guide : EndCodeSnippet
>>
>>  typedef itk::ImageFileWriter<RGBImageType> FileWriterType;
>>
>>  FileReaderType::Pointer reader = FileReaderType::New();
>>  reader->SetFileName(argv[1]);
>>  
>>  DiffusionFilterType::Pointer diffusion = DiffusionFilterType::New();
>>  diffusion->SetNumberOfIterations( atoi(argv[4]) );
>>  diffusion->SetConductanceParameter( atof(argv[3]) );
>>  diffusion->SetTimeStep(0.125);
>>
>>
>>  GradientMagnitudeFilterType::Pointer gradient =
>> GradientMagnitudeFilterType::New();
>>  gradient->SetUsePrincipleComponents(atoi(argv[7]));
>>
>>
>>  WatershedFilterType::Pointer watershed = WatershedFilterType::New();
>>  watershed->SetLevel( atof(argv[6]) );
>>  watershed->SetThreshold( atof(argv[5]) );
>>
>>
>>  typedef itk::Functor::ScalarToRGBPixelFunctor<unsigned long>
>>    ColorMapFunctorType;
>>  typedef itk::UnaryFunctorImageFilter<LabeledImageType,
>>    RGBImageType, ColorMapFunctorType> ColorMapFilterType;
>>  ColorMapFilterType::Pointer colormapper = ColorMapFilterType::New();
>>  
>>  FileWriterType::Pointer writer = FileWriterType::New();
>>  writer->SetFileName(argv[2]);
>>
>>  diffusion->SetInput(reader->GetOutput());
>>  gradient->SetInput(diffusion->GetOutput());
>>  watershed->SetInput(gradient->GetOutput());
>>  colormapper->SetInput(watershed->GetOutput());
>>  writer->SetInput(colormapper->GetOutput());
>>
>>  try    {
>>    writer->Update();
>>    }
>>  catch (itk::ExceptionObject &e)
>>    {
>>    std::cerr << e << std::endl;
>>    }
>>     return 0;
>> }
>>
>>
>>
>>
>>
>> -----Original Message-----
>> From: Laurent Mundeleer [mailto:lmundele at ulb.ac.be]
>> Sent: Thursday, April 29, 2004 6:10 AM
>> To: insight-users at itk.org
>> Subject: [Insight-users] watershed segmentation without RGB?
>>
>>
>> Hi all,
>>
>> I'd like to apply the watershed filter to CT images, is it possible? 
>> In the documentation, it 's specified that RGB values are required...
>> How can I do?
>>
>> Thanks in advance
>>
>> Regards,
>>
>> Laurent
>>
>>  
>>
>