[Insight-users] watershed segmentation without RGB?

Laurent Mundeleer lmundele at ulb.ac.be
Sat, 01 May 2004 12:00:08 +0200


Hi Luis,
I'll look at your example, the interconnection between VTK and ITK is 
something that we allready use for regionGrowing or other stuffs, but 
I'll also look at the other way to do that (because you're right saying 
it's tricky ;-) ).

Thank you,
I'll let you know what I've got

Best Regards,

Laurent


Luis Ibanez wrote:

>
> 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
>>>
>>>  
>>>
>>
>
>
>
>

-- 
********************************************
Laurent Mundeleer
Université Libre de Bruxelles (ULB)
Service des Systèmes Logiques et Numériques (SLN) CP165/57
50, Av. F.Roosevelt
1050 Bruxelles
Belgium
tel : ++32.2.650.22.97
fax : ++32.2.650.22.98
e-mail : lmundele at ulb.ac.be
********************************************