Remove Labels From Label Map#

Synopsis#

Remove the labels from a LabelMap.

Results#

Output:

There are 10 objects.
There are originally 10 objects.
Removing 5 objects.
There are 5 objects remaining.

Code#

C++#

#include "itkImage.h"
#include "itkImageRegionIterator.h"
#include "itkBinaryImageToLabelMapFilter.h"

using ImageType = itk::Image<unsigned char, 2>;
static void
CreateImage(ImageType::Pointer image);

int
main()
{
  auto image = ImageType::New();
  CreateImage(image);

  using BinaryImageToLabelMapFilterType = itk::BinaryImageToLabelMapFilter<ImageType>;
  auto binaryImageToLabelMapFilter = BinaryImageToLabelMapFilterType::New();
  binaryImageToLabelMapFilter->SetInput(image);
  binaryImageToLabelMapFilter->Update();

  // The output of this filter is an itk::LabelMap, which contains itk::LabelObject's
  std::cout << "There are " << binaryImageToLabelMapFilter->GetOutput()->GetNumberOfLabelObjects() << " objects."
            << std::endl;

  std::vector<unsigned long> labelsToRemove;

  std::cout << "There are originally " << binaryImageToLabelMapFilter->GetOutput()->GetNumberOfLabelObjects()
            << " objects." << std::endl;

  // Note: do NOT remove the labels inside the loop! The IDs are stored such that they will change when one is deleted.
  // Instead, mark all of the labels to be removed first and then remove them all together.
  for (unsigned int i = 0; i < binaryImageToLabelMapFilter->GetOutput()->GetNumberOfLabelObjects(); ++i)
  {
    // Get the ith region
    BinaryImageToLabelMapFilterType::OutputImageType::LabelObjectType * labelObject =
      binaryImageToLabelMapFilter->GetOutput()->GetNthLabelObject(i);
    // std::cout << "Region " << i << " has " << labelObject->Size() << " pixels." << std::endl;

    // Mark every other label to be removed
    if (i % 2 == 0)
    {
      labelsToRemove.push_back(labelObject->GetLabel());
    }
  }

  std::cout << "Removing " << labelsToRemove.size() << " objects." << std::endl;
  // Remove all regions that were marked for removal.
  for (unsigned long i : labelsToRemove)
  {
    binaryImageToLabelMapFilter->GetOutput()->RemoveLabel(i);
  }

  std::cout << "There are " << binaryImageToLabelMapFilter->GetOutput()->GetNumberOfLabelObjects()
            << " objects remaining." << std::endl;


  return EXIT_SUCCESS;
}

void
CreateImage(ImageType::Pointer image)
{
  // Create a black image with a white square
  ImageType::IndexType start;
  start.Fill(0);

  ImageType::SizeType size;
  size.Fill(20);

  ImageType::RegionType region(start, size);
  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(0);

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

Classes demonstrated#

template<typename TLabelObject>
class LabelMap : public itk::ImageBase<TLabelObject::ImageDimension>

Templated n-dimensional image to store labeled objects.

LabelMap is an image class specialized in storing the labeled images. It represent the image in a different way than itk::Image. Instead of storing the content of the image in an array of pixels values, it store the a collection of labeled objects, and a background value. This way of storing the content of the image allow an easy and efficient manipulation of the objects in the image.

The LabelMap shares a lot of methods with the itk::Image class. it make it usable as input or output of the itk::ImageToImageFilter for example. However the methods don’t have the same complexity in the 2 classes, because of the different way to store the data. GetPixel() is run in constant time for example in itk::Image, but have a worst case complexity of O(L), where L is the number of lines in the image (imageSize[1] * imageSize[2] for a 3D image).

To iterate over the LabelObjects in the map, use:

for(unsigned int i = 0; i < filter->GetOutput()->GetNumberOfLabelObjects(); ++i)
  {
  FilterType::OutputImageType::LabelObjectType* labelObject =
    filter->GetOutput()->GetNthLabelObject(i);
  }

This implementation was taken from the Insight Journal paper:

https://www.insight-journal.org/browse/publication/176
Author

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

ITK Sphinx Examples:

See itk::LabelMap for additional documentation.