Closing Binary Image#
Synopsis#
Closing a binary image.
Results#
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: