[Insight-users] How to create/draw a sphere surface image mask with 26|6 connectivity?

lynx.abraxas at freenet.de lynx.abraxas at freenet.de
Mon Feb 15 02:47:18 EST 2010


On 13/02/10 15:34:32, Luis Ibanez wrote:
> You could use the following set of classes
>
>
>     1) itkEllipseSpatialObject
>     2) itkSpatialObjectToImageFilter
>     3) itkSimpleContourExtractorImageFilter
>
>
> With (1) you can create a Sphere of the proper size,
> With (2) you can rasterize that sphere into a binary image mask
> With (3) you can extract the contour of the binary image mask
>
>
> The filter (3) allows you to select the "thickness" of
> the contour. You do this by adjusting the value of the
> neighborhood "Radius" parameter.
>

Thanks  a lot Luis for Your quick and helpful answer. With that I could create
the attached test porgram.

Looking at the results slice by slice I wonder if the result is really just 26
connective.  With  that I mean: Does the result have no additional voxels that
would not be necessary to assure 26 connectivity?
How could I create a sphere mask that  has  exactly  only  6  connectivity?  I
thought  of a thickness below 1 but SimpleContourExtractorImageFilter does not
allow that.


I'm not sure if I understand SpatialObject correctly. Are they  some  how  the
correspondence to vtk impicit functions?

> You will find source code guiding examples in
>
>   Insight/Examples/Filtering/
>          SpatialObjectToImage1.cxx
>          SpatialObjectToImage2.cxx
>          SpatialObjectToImage3.cxx

When  searching  the  docs  about  this  I  didn't  find these examples in the
userguide altough they seem to be written for it.

> Anti-aliased versions could be produced in several
> different ways, depending on what you plan to do
> with the resulting contour.
>
> Some of the options for anti-aliased versions are:
>
> A)  Take the aliased contour and pass it as input
>       to the itk::AntiAliasBinaryImageFilter
>
> B) Use either one of the following distance map filters:
>
>         * SignedDanielssonDistanceMapImageFilter
>         * SignedMaurerDistanceMapImageFilter

This is a really cool way to do it.

Thanks again
Lynx

PS: I don't get a progress report from SpatialObjectToImageFilter.

____________________________________

#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>

#include <itkEllipseSpatialObject.h>
#include <itkSpatialObjectToImageFilter.h>
#include <itkSimpleContourExtractorImageFilter.h>
#include "itkFilterWatcher2.h"

int main( int argc, char * argv[] )
    {
    if( argc != 5 )
        {
        std::cerr << "Usage: " << argv[0];
        std::cerr << " outputImage";
        std::cerr << " resolution";
        std::cerr << " radius";
        std::cerr << " thickness";
        std::cerr << std::endl;  
        return EXIT_FAILURE;
        }

    typedef  unsigned char OutputPixelType;

    const unsigned int Dimension = 3;

    typedef itk::Image<OutputPixelType,  Dimension>   OutputImageType;
    typedef itk::EllipseSpatialObject< Dimension >   EllipseType;
    EllipseType::Pointer ellipse    = EllipseType::New();

    ellipse->SetRadius(atof(argv[3]));
    //ellipse->SetDefaultInsideValue(255);
    //ellipse->SetDefaultOutsideValue(0);

    typedef itk::SpatialObjectToImageFilter<EllipseType, OutputImageType> SpatialObjectToImageFilterType;
    SpatialObjectToImageFilterType::Pointer filter= SpatialObjectToImageFilterType::New();
    FilterWatcher watcher(filter, "filter");
    
    int d= atoi(argv[2]);
    OutputImageType::SizeType size;
    size[ 0 ] = d;
    size[ 1 ] = d;
    size[ 2 ] = d;
    filter->SetSize( size );
      
//     OutputImageType::SpacingType spacing;
//     spacing[0] =  2 / size[0]; //use twice the radius;)
//     spacing[1] =  2 / size[1];
//     spacing[2] =  2 / size[2];
//     filter->SetSpacing( spacing );
    filter->SetInsideValue(255);
    filter->SetOutsideValue(0);

    double o= ((d - 1)/2.); //minus 1 probably because of counting starting at 0
    double O[3]={-o, -o, -o};
    filter->SetOrigin(O);
    filter->SetInput(ellipse);
    std::cout << "origin: " << o + 1 << std::endl;

    filter->Update();

    typedef itk::SimpleContourExtractorImageFilter<OutputImageType, OutputImageType> SimpleContourExtractorImageFilterType;
    SimpleContourExtractorImageFilterType::Pointer extractor= SimpleContourExtractorImageFilterType::New();

    extractor->SetInputBackgroundValue(0);
    extractor->SetInputForegroundValue(255);
    extractor->SetOutputBackgroundValue(0);
    extractor->SetOutputForegroundValue(255);

    OutputImageType::SizeType radius;
    radius[ 0 ] = atoi(argv[4]);
    radius[ 1 ] = atoi(argv[4]);
    radius[ 2 ] = atoi(argv[4]);
    extractor->SetRadius(radius);

    extractor->SetInput(filter->GetOutput());
    
    typedef itk::ImageFileWriter<OutputImageType>  WriterType;
    WriterType::Pointer writer = WriterType::New();

    writer->SetFileName(argv[1]);
    //writer->SetInput(filter->GetOutput());
    writer->SetInput(extractor->GetOutput());

    try
        {
        writer->Update();
        }
    catch( itk::ExceptionObject & excp )
        {
        std::cerr << excp << std::endl;
        return EXIT_FAILURE;
        }

    return EXIT_SUCCESS;
    }

 


More information about the Insight-users mailing list