Page MenuHomePhabricator

Closing Project / Reinitialize segmentation sometimes leads to crashes
Closed, ResolvedPublic

Description

(1) Create a 3d-segmentation as in the segmentation checklist, do not confirm.
(2) Close the project
(3) Reload image, reinitialize image and reinit segmentation

Step (2) and (3) sometimes lead to crashes. I attached a log of a crash at step (2).

Event Timeline

Should be fixed for the upcoming release

Unfortunately we could not reproduce this. However, free testing led to regular crashes.

Now we can reproduce this.

(1) Load the scene file located in: E130-Daten/Bilddaten/Bugs Testdata/T19525
(2) Reinit Segmentation
(3) Reinit interpolation
(4) add a new segmentation in a different slice in the top left window.

I think the mitk crashes when we try to add a slice to a 3d interpolation, which has already one slice missing because it has been reduced.

You may also be able to reproduce this bug by
(1) going into 3d interpolation mode
(2) add a few slices
(3) add a very small slice which gets reduced to 0
(4) add another slice

The fix for this bug is divided into 2 parts:

  1. An empty input into mitkReduceContourSetFilter later leads to failed ITK assertion:

For some reason an input to the filter (coming from the mitkSurfaceInterpolationController) could be empty. As mitkReduceContourSetFilter inherits from SurfaceToSurfaceFilter and therefore uses the SetInput method from the mitkSurfaceToSurfaceFilter, it will initialize an output for each input it gets. These outputs are initialized by grafting the input contour (see mitk::SurfaceToSurfaceFilter::CreateOutputForInput) (Graft = create new smart pointer to input contour, same data array is used). This is problematic because of two reasons. a) the mitkReduceContourSetFilter will remove small contours and can therefore have less outputs than inputs, b) mitkReduceContourSetFilter will have nullptr as output if the input is empty.
In the mitkReduceContourSetFilter::GenerateData method, the number of outputs is first set to zero and then incremented for each successfully created output contour. However, when reducing the number of outputs (itk::ProcessObject::SetNumberOfIndexedOutputs(int x) with x < currentNumberOfOutputs) there is an itk assertion (itkAssertInDebugAndIgnoreInReleaseMacro) which ensures that none of the removed outputs is null. This assertion will fail if an input to the filter was null.

This issue is solved by overwriting the SetInput method of the SurfaceToSurface filter. mitkReduceContourSetFilter now has its own SetInput which does not initialize outputs.

  1. After fixing part 1, the 3d interpolation would not work if the first contour drawn by the user was so small that it was removed by the mitkReduceContourSetFilter. This is because the filter has only one input (aka the small contour) and will produce no outputs (because that contour is deleted) (no outputs because number of outputs is set via this->SetNumberOfIndexedOutputs(numberOfOutputs); in GenerateData).

When asked for an output, the filter will now return a nullptr. Interestingly, when we then request an update of the mitkReduceContourSetFilter (as in mitk::SurfaceInterpolationController::Interpolate()) nothing happens, even if more inputs have been added in the meantime.
This is because when update() is called, what itk actually does is retrieving the first output and calling update() on that one: this->GetPrimaryOutput()->Update() (line 1314 in itk::ProcessObject.cxx);
Since the first output is a nullptr the filter will never(!) update again.

This is solved by always maintaining a dummy output in the filter if no other outputs are present. This output is simply a mitk::Surface::Pointer with empty vtkPolyData. Important: whenever we are asking for the outputs of the mitkReduceContourSetFilter and one output is returned we will now have to check whether that one output is an actual output or a dummy output. This is done by checking whether the vtkPolyData of the the output is empty.

User isensee has pushed new remote branch:

bug-19525-interpolation3d-crash-because-of-removed-small-contours