I’m trying to remove the largest island and also the smallest island.
I can get the components correctly, and they are sorted using relabel filter. but I want to threshold the smallest components, and keep the largest, and vice versa, but it seems its not working at all.
constexpr unsigned int Dimension = 3;
using PixelType = unsigned int;
using ImageType_cc = itk::Image<PixelType, Dimension>;
using OutputImageType = itk::Image<unsigned int, Dimension>;
vtkNew<vtkImageCast> castToUint;
castToUint->SetInputData(input);
castToUint->SetOutputScalarTypeToUnsignedInt();
castToUint->Update();
using FilterType_vtk = itk::VTKImageToImageFilter<ImageType_cc>;
auto filter = FilterType_vtk::New();
filter->SetInput(castToUint->GetOutput());
filter->Update();
using ConnectedComponentImageFilterType = itk::ConnectedComponentImageFilter<ImageType_cc, OutputImageType>;
typedef itk::ConnectedComponentImageFilter<ImageType_cc, ImageType_cc> ConnectedComponentType;
typename ConnectedComponentType::Pointer ccfilter = ConnectedComponentType::New();
typedef itk::RelabelComponentImageFilter<ImageType_cc, ImageType_cc> RelabelComponentType;
typename RelabelComponentType::Pointer relabel = RelabelComponentType::New();
ccfilter->SetFullyConnected(false);
ccfilter->SetInput(filter->GetOutput());
relabel->SetInput(ccfilter->GetOutput());
relabel->SetMinimumObjectSize(20);
relabel->Update();
std::cout << relabel->GetNumberOfObjects() << endl;
std::cout << relabel->GetOriginalNumberOfObjects() << endl;
using ImageTypeOutput = itk::Image<unsigned char, 3>;
using FilterType = itk::BinaryThresholdImageFilter<ImageType_cc, ImageTypeOutput>;
auto thresholder = FilterType::New();
thresholder->SetInput(relabel->GetOutput());
thresholder->SetLowerThreshold(0.0);
thresholder->SetUpperThreshold(1.0);
thresholder->Update();
typename ImageTypeOutput::Pointer output = thresholder->GetOutput();
This is the issue. Relabel gives objects integer labels (1, 2, 3, …, n). Thus the output of this thresholder is going to be maybe just the largest object, or probably just an empty image (also known as all zero or all black). You might want to set the lower threshold equal to the number of large objects you want to filter out, and keep the upper threshold at the default (max value).
This is the original number of objects. Some/most of them will be removed by the relabel filter, due to relabel->SetMinimumObjectSize(20);. In my code fragment, this number is completely ignored.
@dzenanz Thanks so much, but Still don’t know how to keep either largest/ and remove smallest, If I want to make two functions one for Keeping Largest, and one for Removing Smallest.
@dzenanz Should I reverse if I want to keep largest, remove smallest, the min, max of thresholding ?
using your code fragments, all the points are removed.
// do not invoke SetMinimumObjectSize
if (removeLargest)
thresholder->SetLowerThreshold(nToFilter);
else // removeSmallest
thresholder->SetUpperThreshold(nToFilter);
3D images frequently have strong topological connectivity. You could explore your image using 3D Slicer. It’s Islands operations use ITK’s connected component and relabel filters.
It works with whatever you instantiate it with, including short. But since the number of islands can be large, it is recommended to use a larger type, otherwise you might run into overflow.
@dzenanz it seems the thresholding is not reliable approach, can you show me an example of keeping largest, removing smallest ? I mean another way or how to use relable components
I want to relabel components with regard to physical size rather than the number of voxels. So a hypothetical SetMinimumObjectPhysicalSize rather than SetMinimumObjectSize. What would be the most efficient way to do that?