Extract Contours From Image

Synopsis

Extract contours from an image.

Results

Output:

There are 2 contours

Contour 0:
[10.5, 19]
[10.4603, 18]
[10.4603, 17]
[10.4603, 16]
[10.4603, 15]
[10.4603, 14]
[10.4603, 13]
[10.4603, 12]
[10.4603, 11]
[10.5, 10]
[10, 9.58579]
[9.5, 10]
[9.5397, 11]
[9.5397, 12]
[9.5397, 13]
[9.5397, 14]
[9.5397, 15]
[9.5397, 16]
[9.5397, 17]
[9.5397, 18]
[9.5, 19]
[10, 19.4142]
[10.5, 19]

Contour 1:
[59.4142, 59]
[59, 58.5]
[58.5, 58]
[58, 57.5]
[57.5, 57]
[57, 56.5]
[56.5, 56]
[56, 55.5]
[55.5, 55]
[55, 54.5]
[54.5, 54]
[54, 53.5]
[53.5, 53]
[53, 52.5]
[52.5, 52]
[52, 51.5]
[51.5, 51]
[51, 50.5]
[50.5, 50]
[50, 49.5]
[49.5, 49]
[49, 48.5]
[48.5, 48]
[48, 47.5]
[47.5, 47]
[47, 46.5]
[46.5, 46]
[46, 45.5]
[45.5, 45]
[45, 44.5]
[44.5, 44]
[44, 43.5]
[43.5, 43]
[43, 42.5]
[42.5, 42]
[42, 41.5]
[41.5, 41]
[41, 40.5]
[40.5, 40]
[40, 39.5858]
[39.5858, 40]
[40, 40.5]
[40.5, 41]
[41, 41.5]
[41.5, 42]
[42, 42.5]
[42.5, 43]
[43, 43.5]
[43.5, 44]
[44, 44.5]
[44.5, 45]
[45, 45.5]
[45.5, 46]
[46, 46.5]
[46.5, 47]
[47, 47.5]
[47.5, 48]
[48, 48.5]
[48.5, 49]
[49, 49.5]
[49.5, 50]
[50, 50.5]
[50.5, 51]
[51, 51.5]
[51.5, 52]
[52, 52.5]
[52.5, 53]
[53, 53.5]
[53.5, 54]
[54, 54.5]
[54.5, 55]
[55, 55.5]
[55.5, 56]
[56, 56.5]
[56.5, 57]
[57, 57.5]
[57.5, 58]
[58, 58.5]
[58.5, 59]
[59, 59.4142]
[59.4142, 59]

Code

C++

#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkContourExtractor2DImageFilter.h"
#include "itkApproximateSignedDistanceMapImageFilter.h"

using UnsignedCharImageType = itk::Image<unsigned char, 2>;
using FloatImageType = itk::Image<float, 2>;

static void
CreateImage(UnsignedCharImageType::Pointer image);

int
main(int, char *[])
{
  UnsignedCharImageType::Pointer image = UnsignedCharImageType::New();
  CreateImage(image);

  using ApproximateSignedDistanceMapImageFilterType =
    itk::ApproximateSignedDistanceMapImageFilter<UnsignedCharImageType, FloatImageType>;
  ApproximateSignedDistanceMapImageFilterType::Pointer approximateSignedDistanceMapImageFilter =
    ApproximateSignedDistanceMapImageFilterType::New();
  approximateSignedDistanceMapImageFilter->SetInput(image);
  approximateSignedDistanceMapImageFilter->SetInsideValue(255);
  approximateSignedDistanceMapImageFilter->SetOutsideValue(0);
  approximateSignedDistanceMapImageFilter->Update();

  using ContourExtractor2DImageFilterType = itk::ContourExtractor2DImageFilter<FloatImageType>;
  ContourExtractor2DImageFilterType::Pointer contourExtractor2DImageFilter = ContourExtractor2DImageFilterType::New();
  contourExtractor2DImageFilter->SetInput(approximateSignedDistanceMapImageFilter->GetOutput());
  contourExtractor2DImageFilter->SetContourValue(0);
  contourExtractor2DImageFilter->Update();

  std::cout << "There are " << contourExtractor2DImageFilter->GetNumberOfOutputs() << " contours" << std::endl;


  for (unsigned int i = 0; i < contourExtractor2DImageFilter->GetNumberOfOutputs(); ++i)
  {
    std::cout << "Contour " << i << ": " << std::endl;
    ContourExtractor2DImageFilterType::VertexListType::ConstIterator vertexIterator =
      contourExtractor2DImageFilter->GetOutput(i)->GetVertexList()->Begin();
    while (vertexIterator != contourExtractor2DImageFilter->GetOutput(i)->GetVertexList()->End())
    {
      std::cout << vertexIterator->Value() << std::endl;
      ++vertexIterator;
    }
    std::cout << std::endl;
  }

  return EXIT_SUCCESS;
}

void
CreateImage(UnsignedCharImageType::Pointer image)
{
  // Create an image
  itk::Index<2> start;
  start.Fill(0);

  itk::Size<2> size;
  size.Fill(100);

  itk::ImageRegion<2> region(start, size);
  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(0);

  // Create a line of white pixels
  for (unsigned int i = 40; i < 60; ++i)
  {
    itk::Index<2> pixel;
    pixel.Fill(i);
    image->SetPixel(pixel, 255);
  }

  // Create another line of pixels
  for (unsigned int i = 10; i < 20; ++i)
  {
    itk::Index<2> pixel;
    pixel[0] = 10;
    pixel[1] = i;
    image->SetPixel(pixel, 255);
  }

  using WriterType = itk::ImageFileWriter<UnsignedCharImageType>;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName("image.png");
  writer->SetInput(image);
  writer->Update();
}

Classes demonstrated