Smooth Binary Image Before Surface Extraction

Synopsis

This example introduces the use of the AntiAliasBinaryImageFilter. This filter expects a binary mask as input. With level sets, it smooths the image by keeping the edge of the structure within a one pixel distance from the original location. It is usually desirable to run this filter before extracting an isocontour with surface extraction methods.

Results

Input image

Input image

Output image

Output image

Code

C++

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkAntiAliasBinaryImageFilter.h"

int
main(int argc, char * argv[])
{
  if (argc < 3)
  {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " <inputImage> <outputImage>";
    std::cerr << " [maximumRMSError]";
    std::cerr << " [numberOfIterations]";
    std::cerr << " [numberOfLayers]" << std::endl;
    return EXIT_FAILURE;
  }

  const char * inputFileName = argv[1];
  const char * outputFileName = argv[2];
  double       maximumRMSError = 0.001;
  if (argc > 3)
  {
    maximumRMSError = std::stod(argv[3]);
  }
  int numberOfIterations = 50;
  if (argc > 4)
  {
    numberOfIterations = std::stoi(argv[4]);
  }
  int numberOfLayers = 2;
  if (argc > 5)
  {
    numberOfLayers = std::stoi(argv[5]);
  }

  constexpr unsigned int Dimension = 2;

  using PixelType = float;

  using ImageType = itk::Image<PixelType, Dimension>;

  using ReaderType = itk::ImageFileReader<ImageType>;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFileName);

  using FilterType = itk::AntiAliasBinaryImageFilter<ImageType, ImageType>;
  FilterType::Pointer filter = FilterType::New();
  filter->SetInput(reader->GetOutput());
  filter->SetMaximumRMSError(maximumRMSError);
  filter->SetNumberOfIterations(numberOfIterations);
  filter->SetNumberOfLayers(numberOfLayers);

  using WriterType = itk::ImageFileWriter<ImageType>;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputFileName);
  writer->SetInput(filter->GetOutput());
  try
  {
    writer->Update();
  }
  catch (itk::ExceptionObject & error)
  {
    std::cerr << "Error: " << error << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

Python

#!/usr/bin/env python
import itk

if len(sys.argv) != 6:
    print("Usage: " + sys.argv[0] + " <inputImage> <outputImage> "
          "<maximumRMSError> <numberOfIterations> <numberOfLayers>")
    sys.exit(1)

inputImage = sys.argv[1]
outputImage = sys.argv[2]
maximumRMSError = float(sys.argv[3])
numberOfIterations = int(sys.argv[4])
numberOfLayers = int(sys.argv[5])

PixelType = itk.F
Dimension = 2
ImageType = itk.Image[PixelType, Dimension]

ReaderType = itk.ImageFileReader[ImageType]
reader = ReaderType.New()
reader.SetFileName(inputImage)

AntiAliasFilterType = itk.AntiAliasBinaryImageFilter[ImageType, ImageType]
antialiasfilter = AntiAliasFilterType.New()
antialiasfilter.SetInput(reader.GetOutput())
antialiasfilter.SetMaximumRMSError(maximumRMSError)
antialiasfilter.SetNumberOfIterations(numberOfIterations)
antialiasfilter.SetNumberOfLayers(numberOfLayers)

WriterType = itk.ImageFileWriter[ImageType]
writer = WriterType.New()
writer.SetFileName(outputImage)
writer.SetInput(antialiasfilter.GetOutput())

writer.Update()

Classes demonstrated