Page MenuHomePhabricator

[Segmentation] [Bug] 2D RGB image not correctly handled by SegPreviewTool API tool
Open, NormalPublic

Description

Segmentation tools deriving from SegPreviewTool class overrides a virtual method DoUpdatePreview to work on applying segmentation algorithms.

virtual void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, LabelSetImage* previewImage, TimeStepType timeStep) = 0;

However, the input parameters inputAtTimeStep is always single channel even if the loaded image on the workbench is 2D RGB.
ie. inputAtTimeStep->GetNumberOfChannels() = 1

Event Timeline

After a little debugging, I see that even DataNode::GetData() returns single channel Image.
eg. dynamic_cast<const Image *>(m_SegmentationInputNode->GetData())
SegPreviewTool class uses this image for further processing.

Be carefull. RGB channels of an RGB image are not stored in different mitk::Image channels currently. Every thing is stored in one channel. But the channel has the pixel type "rgba". So the channels are encoded in each pixel.

That's why you only get only one channel if you use GetData().

Oh ok. Yes, I can the see the pixel type "rgb". Also, when I save the mitk::Image object using IOUtils::Save, I can see (in python) that the written image is 3 channel.
But the issue still occurs, channel is information is ultimately lost here in mitk::SegWithPreviewTool::UpdatePreview:

if (nullptr != this->GetWorkingPlaneGeometry())
 {
          feedBackImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), inputImage, timePoint);
          currentSegImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), workingImage, timePoint);
}
this->DoUpdatePreview(feedBackImage, currentSegImage, previewImage, timeStep);

The feedBackImage (& currentSegImage) is really 2D with single channel since the SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint component arg is zero by default.
So, setting the component arg explicitly to -1 helps:
feedBackImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), inputImage, timePoint, -1);
Now, verifying the feedBackImage in python after writing in to a file using IOUtils::Save, gives me 3 channel image. Voila! Seems like a fix but, it opens a can-of-worms(?).

  1. feedBackImage has no pixeltype. feedBackImage->GetPixelType().GetPixelTypeAsString() prints nothing. Its empty.
  2. feedBackImage is incompatible with ITK filters for LevelWindow and File writing. MITK crashes without any obvious error message.

Your "solution" is not a real fix. It just exploits a bug/undefined behavior. So do not do it

Please check the following:
Path locally mitkExtractSliceFilter Line 448

if (numberOfScalarComponent > 1 && static_cast<unsigned int>(numberOfScalarComponent) >= m_Component)

in such a way that the if block is never entered (e.g. by commenting it out ot setting 1 to 4...).
Then test it again. Now you should have rgb slices if it is an rgb image and none if not, right?

If this is the case then the problem is a feature of mitkExtractSliceFilter's implementation as it always extracts components. One would need to enhance the filter to also allow to configure the filter in a way that it keeps all component (so the if block is always skipped even for multi component pixels).

Yes, after commenting the 4 lines in the mitkExtractSliceFilter I am getting 3 component image.
Also, found out that the following works instead of commenting the snippet out:
Comment vectorComponentExtractor->SetComponents(m_Component); and pass on exact component needed to vectorComponentExtractor->SetComponents(0,1,2);.

However, the 2 concerns raised for the final sliced image (feedBackImage) still exists. Nothing changed.

floca triaged this task as Normal priority.Oct 11 2023, 11:20 AM