label map overlay .. I dont' understand the problem ?

For some reason the LabelMapOverlay doesn’t work on my label map created from the ChangeLabel filter. I also tried running it directly on the output of ConnectedComponent() with the same result.
What is the problem? how do I diagnose the problem ?

    319 filtim=sitk.ChangeLabel(sizeim,dict(roundlist))


326 print filtim
327 coloursize=sitk.LabelMapOverlay(filtim,ushortim)

Here’s the error output
Traceback (most recent call last):
File “./simple_find_biggest_sitk_in.py”, line 327, in
coloursize=sitk.LabelMapOverlay(filtim,ushortim)
File “/home/kny48981/.local/lib/python2.7/site-packages/SimpleITK/SimpleITK.py”, line 41588, in LabelMapOverlay
return _SimpleITK.LabelMapOverlay(*args, **kwargs)
RuntimeError: Exception thrown in SimpleITK LabelMapOverlay: /tmp/SimpleITK/Code/Common/include/sitkDualMemberFunctionFactory.hxx:201:
sitk::ERROR: Pixel type: 32-bit unsigned integer is not supported in 3D byN3itk6simple26LabelMapOverlayImageFilterE

Heres the object print-out of filtim from line 326
Image (0x7f3801db1da0)
RTTI typeinfo: itk::Image<unsigned int, 3u>
Reference Count: 1
Modified Time: 39409
Debug: Off
Object Name:
Observers:
none
Source: (none)
Source output name: (none)
Release Data: Off
Data Released: False
Global Release Data: Off
PipelineMTime: 39401
UpdateMTime: 39408
RealTimeStamp: 0 seconds
LargestPossibleRegion:
Dimension: 3
Index: [0, 0, 0]
Size: [58, 53, 204]
BufferedRegion:
Dimension: 3
Index: [0, 0, 0]
Size: [58, 53, 204]
RequestedRegion:
Dimension: 3
Index: [0, 0, 0]
Size: [58, 53, 204]
Spacing: [1, 1, 1]
Origin: [0, 0, 0]
Direction:
1 0 0
0 1 0
0 0 1

  IndexToPointMatrix:
1 0 0
0 1 0
0 0 1

  PointToIndexMatrix:
1 0 0
0 1 0
0 0 1

  Inverse Direction:
1 0 0
0 1 0
0 0 1

  PixelContainer:
    ImportImageContainer (0x7f38023aca80)
      RTTI typeinfo:   itk::ImportImageContainer<unsigned long, unsigned int>
      Reference Count: 1
      Modified Time: 39406
      Debug: Off
      Object Name:
      Observers:
        none
      Pointer: 0x7f38043ace00
      Container manages memory: true
      Size: 627096
      Capacity: 627096

Hello Robert!

So there are two distinct concepts in ITK/SimpleITK

Label Images” - A scalar itk::Image where the pixels represent scalar label values and the data is stored as an n-d array. There are represented in SimpleITK with enums such as sitk::sitkUInt8, sitk::sitkUInt32 etc.

LabelMap Images” - These are itk::LabelMap, a class derived from itk::ImageBase. These also represent an image of scalar labels, but the data is stored as run length encode (RLE) label objects. This is an efficient ways to store spares labels, and efficient data structor for label based operations such as relabeling or deleting select objects. In SimpleITK these are repressed with images that have the enum sitk::sitkLabelUInt8, sitk::sitkLabelUInt32, etc.

These terms are some what confused in 3D Slicer as they call “Label Image”, “LabelMaps”.

So, the filters with “LabelMap” in the name generally expect a “LabelMap Image”.

So your image, “filtim” is of sitk.sitkUInt32, which a “Label Image”. Here are two options:

  1. Cast the Image to sitk.sitkLabelUInt8
sitk.LabelMapOverlay(sitk.Cast(filtim,sitk.sitkLabelUIInt8),ushortim)

The Cast filter actually just calls the LabelImageToLabelMap filter. So the following is the same:

sitk.LabelMapOverlay(sitk.LabelImageToLabelMap(filtim),ushortim)
  1. The other option is to use the “Label Image” variant of the filter:
sitk.LabelOverlay(filtim,ushortim)

Hope that help!
Brad

2 Likes

Yes, that clarifies things a little … now it’s at least as clear as mud :slight_smile: ! I.e I can make my code work but now I think its done the wrong way … It sounds like I really should be using the LabelMapImage in the first place; once obtaining a binary threshold with separated objects and applying some connected components and then wanting to filter on various attributes e.g. roundness, touching boundary, etc. on images or timeseries that will be a lot bigger than the test case. So runlength encoded storage for manipulating these things makes a lot of sense. Which is why I would have thought I had such a creature already; what is the output of ConnectedComponents and why isn’t it one of those??

I have implemented the same project before, a long time ago , in ITK C++ version 3 and it’s mostly a lot easier in Simpleitk+Python … but there’s (a) lots of changes, ok , for the better! but, (b) not clear explanation, please see the Doxygen for ConnectedComponents ?

So do I now understand that the output of LabelIntensityStatisticsImageFilter is actually one of the “LabelMap Image” objects, which could be overlain directly by the previous filter? But can you use ChangeLabel filter on it, it seems like it wants the “Label Image” ??

Note Bradely: I mostly used your stackoverflow reply https://stackoverflow.com/questions/40720176/how-to-extract-labels-from-a-binary-image-in-simpleitk-in-python in implementing that part of what I am working on in simpleITK python .

And a minor annoyance: when changing my program from LabelMapOverlay to LabelOverlay, it becomes immediately clear that these functionally nearly identical filters have their primary input parameters in the opposite order – (label, original) versus (original,label)

1 Like

At first in ITK there was just the regular images then the LabelMap module was contributed to ITK via the Insight Journal: http://hdl.handle.net/1926/584 As the ConnectedComponentsI and the BinaryImageToLabelMap filters produce different output data structures, why both have their purpose.

Great to hear that it is easier and for the better! :slight_smile:

As I just said in another thread

We really should be doing better with our SimpleITK Doxygen. As of right now the description for the filters are just taken from ITK, with all the features exposed from the C++ interface. We should really mark this as coming for C++ ITK, and provide brief info about the SimpleITK simplification done, or implementation choices made.

However, for the ConnectedComponents doxygen, the filter does not talk about C++ or features that have been simplified for the interface, so I am no sure why you reference this particular one?

The LabelMap version of ConnectedComponentsImageFilter is BinaryImageToLabelMapImageFilter and the LabelMap version of ChangeLabelImageFilter is ChangeLabelLabelMapFilter. So the output of BinaryImageToLabelMapFilter can be used as input to the ChangeLabelIamgeFilter. That is not a typeo, Label is repeated in the filter name, the ITK naming conventions follow strict conventions. They make since, really then do.

So… The SimpleITK filter sitk::LabelIntensityStatisticsImageFilter is a case where the Doxygen was taken from the underlying ITK class, itk::LabelImageToStatisticsLabelMapFilter and it is not good to say the least, combined with that little changes that SimpleITK made to the interface it is now double-plus not good. For SimpleITK filter, this is a case where the input is not a LabelMap but a scalar label image, and there is no output image/LabelMap. The computed statistics are just available with Get methods of the filter after execution.

Hope that helps.

THe reason I reference the ConnectedComponents … well… how would you recommend that ,starting from very little, that I should locate some information about how to find the connected components of the image using simpleITK? I googled for “simpleitk connected components” and found the doxygen page. I also sometimes open the list of class names from Doxygen and do a search for what I think it might be called, so indeed the naming scheme can help. However, the novel terminology that ‘Label Map’ is seemingly a synonym for ‘Connected Components’ is not pulled up by that search strategy. I could gripe about how I don’t even agree that it’s a good name but I suppose that ship has sailed !