[Insight-users] relabelComponentImageFilter: bug and comments

Miller, James V (Research) millerjv at crd.ge.com
Fri Jul 23 09:22:27 EDT 2004


Jerome,

There are two methods in RelabelComponentImageFilter to get the size of
objects.  

 const std::vector<unsigned long>& GetSizeOfObjectsInPixels() const;
 const std::vector<float>& GetSizeOfObjectsInPhysicalUnits() const;

The return type to the method GetSizeOfObjectsInPhysicalUnits() was fixed
on Feb 2, 2004 and is available via cvs.


The next two issues are intertwined between the
ConnectedComponentImageFilter
and the RelabelCOmponentImageFilter.

The ConnectedComponentImageFilter has to have all the input available to 
properly determine the connected components.  The
RelabelComponentImageFilter
only needs the entire input (presumably the output of the
ConnectedComponentImageFilter) so that it can properly sort the labels based
on object size. Since the ConnectedComponentImageFilter produces all the
output
anyway, there really is no hardship in having the input to the 
RelabelComponentImageFilter be the entire input. The actual relabeling of 
the connected components is only performed on the requested region of the
output.

If you want to relabel the objects within a region or compute the connected
components within a region, you can place a RegionOfInterestImageFilter, a
CropImageFilter, or an ExtractImageFilter prior to the
RelabelComponentImageFilter.

For the overflow in number of objects, you should be careful how you select
output image type for the ConnectedComponentImageFilter and
RelabelComponentImageFilter.  For the reasons you
mentioned, I always used an unsigned long pixel type for the output of the 
ConnectedComponentImageFilter and RelabelComponentImageFilter.  

Note that the ConnectedComponentImageFilter already has code to check
whether
it has run out of labels (about to overflow).  When this occurs, it issues
a warning (actually a warning per pixel) and uses the maximum label for 
all components after that point.

Jim


-----Original Message-----
From: jerome schmid [mailto:jerome.schmid at ircad.u-strasbg.fr]
Sent: Friday, July 23, 2004 4:35 AM
To: insight-users at itk.org
Subject: [Insight-users] relabelComponentImageFilter: bug and comments


Hi itk users,

I have a few comments on the relabelComponentImageFilter.

First of all the "bug":

in .h the container for size of connected component in physical units in
defined as:
std::vector<float> m_SizeOfObjectsInPhysicalUnits;

But the Get function GetSizeOfObjectsInPhysicalUnits() const returns

const std::vector<unsigned long>& GetSizeOfObjectsInPhysicalUnits() const,
i.e an unsigned *long* vector instead of a *float* vector.

Here are my remarks:

This filter enlarges the requested region setting it to the largest
possible, because it considers that for connected components (CC) reasons,
all the image must be considered. In the attached picture you can see that
the shape is one CC but in the requested region ( red square ), if this
region is considered alone, there a 2 CCs. So the filter explore all the
image in order to return *1* CC for the requested region. But sometimes we
may know that this phenomenum can appear and we can, for instance, add a
border to image in order to connect the 2 CCs in one. The advantage of doing
this is that you must *not* explore the whole image and study the CCs, and
you save a lot of time. I have so created a localRelabelComponentImage
filter simply by removing the enlarge region function.

Now another remark. Imagine that you have images which pixel type is
unisgned char. It means that there are only 256 possible labels for relabel
component filter or, 1 for background and 255 for the rest. The problem is
that if you have more than *255* CCs, there will be an "overlap": the label
256 will be added in the label 1 for casting reason ( unisgned char i =
static_cast< unisgned char >( 256 ). i == 1! ). So if you are looking for
the biggest CC, and it can be the case often, you will find a lot of regions
*disconnected* ( so it is not a CC...!) with label 1...In order to avoid
this, because it is my particular use, I have considered that every label
superior to 255 wil be added to the last label group:

		if( m_NumberOfObjects > (
NumericTraits<OutputPixelType>::max() - 1 ) )
		{
			// There are not enough labels in output image due
to its internal type
limitations
			// set highest label to max
			while ( !oit.IsAtEnd() )
			{
			inputValue = it.Get();

			if (inputValue !=
NumericTraits<InputPixelType>::Zero)
			{
				// Test in order to detect label too high
				unsigned long label	=
relabelMap[inputValue];
				// lookup the mapped label
				if( static_cast< double >( label ) >
maxOutputValueDbl )
				{
					// our strategy every too big label
is set to max
					outputValue	= maxOutputValue;
				}
				else
				{
					outputValue =
static_cast<OutputPixelType>(label);
				}

				oit.Set( outputValue );
			}

			// increment the iterators
			++it;
			++oit;
			progress.CompletedPixel();
			}

		}
		else
		{
			// no limitation problem
			while ( !oit.IsAtEnd() )
			{
			inputValue = it.Get();

			if (inputValue !=
NumericTraits<InputPixelType>::Zero)
			{
				unsigned long label	=
relabelMap[inputValue];
				outputValue =
static_cast<OutputPixelType>(label);
				oit.Set( outputValue );
			}

			// increment the iterators
			++it;
			++oit;
			progress.CompletedPixel();
			}
		}

I think so that a good idea will be to put a flag like:

limitationOn	== m_NumberOfObjects > (
NumericTraits<OutputPixelType>::max() - 1 )

and the user will check it, to see if there is a limitation problem. I write
this because it takes me a lot of time to understand what happened the first
time!!!!

Here all these remarks have been already submitted sorry!

Regards,

Jerome Schmid


More information about the Insight-users mailing list