Closing Binary Image#

Synopsis#

Closing a binary image.

Results#

../../../../_images/ClosingBinaryImageQuickView.png

Output In VTK Window#

Output:

Radius: 5

Code#

C++#

#include "itkImage.h"
#include "itkBinaryMorphologicalClosingImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkBinaryBallStructuringElement.h"
#include "itkSubtractImageFilter.h"

#ifdef ENABLE_QUICKVIEW
#  include "QuickView.h"
#endif

namespace
{
using ImageType = itk::Image<unsigned char, 2>;
}

static void
CreateImage(ImageType * const image);

int
main(int argc, char * argv[])
{
  ImageType::Pointer image;
  unsigned int       radius = 5;
  std::string        outputFilename = "Output.png";

  if (argc >= 4)
  {
    image = itk::ReadImage<ImageType>(argv[1]);

    std::stringstream ss(argv[2]);
    ss >> radius;

    outputFilename = argv[3];
  }
  else
  {
    image = ImageType::New();
    CreateImage(image);
  }

  std::cout << "Radius: " << radius << std::endl;
  using StructuringElementType = itk::BinaryBallStructuringElement<ImageType::PixelType, ImageType::ImageDimension>;
  StructuringElementType structuringElement;
  structuringElement.SetRadius(radius);
  structuringElement.CreateStructuringElement();

  using BinaryMorphologicalClosingImageFilterType =
    itk::BinaryMorphologicalClosingImageFilter<ImageType, ImageType, StructuringElementType>;
  auto closingFilter = BinaryMorphologicalClosingImageFilterType::New();
  closingFilter->SetInput(image);
  closingFilter->SetKernel(structuringElement);
  closingFilter->Update();

  using SubtractType = itk::SubtractImageFilter<ImageType>;
  auto diff = SubtractType::New();
  diff->SetInput1(closingFilter->GetOutput());
  diff->SetInput2(image);

#ifdef ENABLE_QUICKVIEW
  QuickView         viewer;
  std::stringstream desc;
  desc << "Original ";
  viewer.AddImage(image.GetPointer(), true, desc.str());

  std::stringstream desc2;
  desc2 << "BinaryClosing, radius = " << radius;
  viewer.AddImage(closingFilter->GetOutput(), true, desc2.str());

  std::stringstream desc3;
  desc3 << "BinaryClosing - Original";
  viewer.AddImage(diff->GetOutput(), true, desc3.str());
  viewer.Visualize();
#endif

  itk::WriteImage(closingFilter->GetOutput(), outputFilename);
  return EXIT_SUCCESS;
}


void
CreateImage(ImageType * const image)
{
  // Create an image with a gray square
  itk::Index<2> corner = { { 0, 0 } };

  itk::Size<2> size;
  unsigned int NumRows = 200;
  unsigned int NumCols = 300;
  size[0] = NumRows;
  size[1] = NumCols;

  itk::ImageRegion<2> region(corner, size);

  image->SetRegions(region);
  image->Allocate(true);

  // Make a square
  for (unsigned int r = 40; r < 100; ++r)
  {
    for (unsigned int c = 40; c < 100; ++c)
    {
      itk::Index<2> pixelIndex;
      pixelIndex[0] = r;
      pixelIndex[1] = c;

      image->SetPixel(pixelIndex, 50);
    }
  }
}

Classes demonstrated#

template<typename TInputImage, typename TOutputImage, typename TKernel>
class BinaryMorphologicalClosingImageFilter : public itk::KernelImageFilter<TInputImage, TOutputImage, TKernel>

binary morphological closing of an image.

This filter removes small (i.e., smaller than the structuring element) holes and tube like structures in the interior or at the boundaries of the image. The morphological closing of an image “f” is defined as: Closing(f) = Erosion(Dilation(f)).

The structuring element is assumed to be composed of binary values (zero or one). Only elements of the structuring element having values > 0 are candidates for affecting the center pixel.

This code was contributed in the Insight Journal paper: “Binary morphological closing and opening image filters” by Lehmann G. https://www.insight-journal.org/browse/publication/58

Author

Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France.

See

MorphologyImageFilter, GrayscaleDilateImageFilter, GrayscaleErodeImageFilter

ITK Sphinx Examples:

See itk::BinaryMorphologicalClosingImageFilter for additional documentation.