Opening a Binary Image#

Synopsis#

Opening a binary image.

Results#

../../../../_images/OpeningBinaryImageQuickView.png

Output In VTK Window#

Output:

Radius: 5

Code#

C++#

#include "itkImage.h"
#include "itkBinaryMorphologicalOpeningImageFilter.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 BinaryMorphologicalOpeningImageFilterType =
    itk::BinaryMorphologicalOpeningImageFilter<ImageType, ImageType, StructuringElementType>;
  auto openingFilter = BinaryMorphologicalOpeningImageFilterType::New();
  openingFilter->SetInput(image);
  openingFilter->SetKernel(structuringElement);
  openingFilter->Update();

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

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

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

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

  itk::WriteImage(openingFilter->GetOutput(), outputFilename);

  return EXIT_SUCCESS;
}


void
CreateImage(ImageType * const image)
{
  // Create an image with 2 connected components
  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 BinaryMorphologicalOpeningImageFilter : public itk::KernelImageFilter<TInputImage, TOutputImage, TKernel>

binary morphological opening of an image.

This filter removes small (i.e., smaller than the structuring element) structures in the interior or at the boundaries of the image. The morphological opening of an image “f” is defined as: Opening(f) = Dilatation(Erosion(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::BinaryMorphologicalOpeningImageFilter for additional documentation.