3D rendering bug for models imported to segment?

There is something confusing going on when I try to import a model to segment (either via right-click in SH and choose convert to segmentation, or use SlicerMorph’s ImportSurfaceToSegment module).

Here is a screenshot displaying the 3D visualization of original model (yellow), SH method and ImportSurfaceToSegment (cyan);

There is no difference in detail. Visibilities are set through SH (drag and drop).

If I switch to Segment Editor, Show 3D button is pressed (enabled). If toggle it off and back on that’s what I get, a smoothened model (cyan):

That’s because smoothing is enabled. So I turned it off, then instead of the original image, I get this more noisy looking surface:

Whatever level of smoothing I chose, I can’t seem to reproduce the original cyan model created after the conversion. The details seems to have been lost (specifically I am interested in suture boundaries). This also happens on the segmentation I derive from right-clicking in subject hierarchy.

Where is the loss of information is coming (or is the initial rendering is incorrect)?

That is “normal” if the source model is a triangulated surface and the operation you perform requires conversion to a binary labelmap representation, which is an inherently lossy operation. You can in theory reduce the loss to an arbitrarily small level by sampling at a higher resolution (changing the labelmap resolution) at the cost of using more memory (potentially a lot more memory). This could be a motivation to use one of the super-high memory JS2 instances.

1 Like

So the initial model displayed after the conversion is not the real model?

It is, but it’s the surface model representation of the segmentation.

There are specific instructions here.

That I understand, what is confusing is that I can’t seem to recover that representation when I toggle the Show 3D switch on and off.

My guess would be that the “show 3d” operation is really the “build s surface model from the binary labelmap representaton” under the hood. I agree that maybe it should be have like the “eye” icons in the subject hierarchy and not convert if not needed.

I don’t really have a preference, but the current behavior is confusing to say the least. If the conversion is lossy, then the first rendering (without going into the segment editor) should reflect that. if it is not, then I should be to recover that detail through the Show 3D button of segment editor.

I agree, if my theory of the show 3d button is correct then it is a bit misleading in this case. Maybe @lassoan or @cpinter can comment. I do think that showing the surface model at first makes sense, since you can do operations on segmentations without creating binary labelmaps but having the show 3D button change representations behind the scenes seems wrong.

“Show 3D” button creates/deletes closed surface representation. The current button text is chosen because showing a segmentation in 3D is the primary use of the closed surface representation.

When you create a segmentation then the source representation is always binary labelmap, even if you import a model into it. The closed surface representation is generated from the labelmap representation when needed; for example when closed surface representation is removed/creaated; or when saving the scene to file and then loading from it; or when editing the segment.

We preserve all the available representations as much as possible, because that allows moving segments between segmentations without losing any information (e.g., temporarily move a segment into another segmentation and later move it back).

But that’s not what I am observing, I think. Unless I am missing out something, when I import the model as a segmentation by right-clicking and choosing “convert segmentation”, the final 3D rendering show is identical to the model one I just used. Then I toggle 3D view off and on again, I do see the new closed surface representation generated off the labelmap (which is noisier and some details are lost). From the explanation you have given, the first rendering after the conversion is an incorrect representation of the segmentation (it should have rendered using the labelmap generated).

This behavior is misleading, and the difference is noticeable enough to make people think they are doing something wrong, as suddenly the 3D view is less detailed than what it was before. Yet all of that was already lost during the conversion closed surface to labelmap representation, just the view didn’t get updated (at least this is how I interpret it).

As I wrote above, it is important that we only update a representation if needed. If we already have a representation then we use it. This allows many useful features, for example organizing segments by moving them between segments is a lossless operation.

If we can find a way how to make segmentations easier to understand then that’s great, but segmentation is inherently complex, so I think it is unavoidable that time to time people are surprised to discover some new details.

When you import a model node to a segmentation, it will do three things:

  1. Create a new segmentation with the default binary labelmap segmentation
  2. Set the imported model as closed surface representation
  3. Convert it into binary labelmap so that we have a valid source representation (lossy)

At this point, the shown closed surface is the original one you imported.

Then, when you turn off Show 3D, the closed surface gets removed. When you turn it on again, the closed surface is converted from the source representation (lossy).

As I remember we remove the closed surface instead of just hiding it, because if you edit the labelmap in Segment Editor, we don’t want to continually re-convert the surface if we don’t even see it (we always need to keep valid representations). As Andras says this infrastructure is inherently complex. @muratmaga If you’re interested you can read about motivations, design, etc here or here. Or feel free to keep asking of course :slight_smile:

Thanks @cpinter and @lassoan for the extra explanation and details. To me the difference is that @muratmaga expects the “show 3D” to operate just like the visibility eye icons in other parts of the application, while what it really does is to tell Slicer to update the surface representation to match the labelmap representation and keep it updated as long as that mode is active. Although it’s an edge case, I could see this being a bit of a trap if instead of loading a file, the user created the surface representation in a way that’s hard to recreate leading to data loss. Also once this happens you have no way to go back and adjust the resampling geometry.

It seems easy to detect this situation (existing surface representation but no labelmap) and ask the user if they really want to replace their current surface. I think this case happens anytime you do a Segment Editor operation that requires a labelmap and people may not know that or have any other easy way to learn.

I don’t really see this happening. The only way you can get to this point is to convert an existing model node to a segmentation node. You’ll still have the model node unless you explicitly delete it.

That button was called something else but users did not understand it so we had to simplify the message. I’m open to renaming it again…

Yes any time the labelmap is modified, the closed surface is reconverted. I have to think a bit more, but I don’t see an elegant way for deciding if a surface is the “actual source”, unless with a new flag, which is an idea I don’t like.

As I remember there was also a discussion about the source representation when people import a model to an empty segmentation. To me the most reasonable solution would be to set the source representation as closed surface (because that is what is happening), and then when the user wants to edit, a warning already pops up about changing the source. But I also remember that the outcome of that discussion was the current way (not sure anymore why).

Okay, that’s fair. I was thinking that you could load a surface model as a segmentation but I checked and I see that’s not possible.

It is possible but I think it is restricted for OBJ format for some reason. Not sure why format matters?

Good question. I used vtk and it was not an option.

I just loaded an STL as segmentation, and the source representation is Closed surface. So the issue this topic is about (show-hide 3D and the model deteriorates) does not exist in this use case.

@muratmaga can you replicate the issue without the SlicerMorph modules? They might be side-stepping the Slicer native behavior.

I just tried loading and stl file as a segmentation. It works fine and when I try to paint I need to select a source volume and then it warns that details may be lost due to the labelmap. This seems quite reasonable to me, but something different must be going on in the ImportSurfaceToSegment process that bypasses the warning.

The import feature is quite simple:

  1. The SH plugin creates a new segmentation with default options (binary labelmap source)
  2. Calls the segmentations logic (ImportModelToSegmentationNode), which simply creates a segment from the model’s polydata and adds it to the segmentation

I found a thread that is about the same thing. It’s from five years ago and I said the same thing; it seems odd that the source representation is labelmap when we import a model to segmentation.

I think it would be more correct adding a line in the SH plugin that sets closed surface as source representation. But again I’m not sure why this was kept like this. @lassoan if you remember please let us know. You see way more use cases than I and there must have been a good reason. Thanks!