The reading itself seems to work but as soon as the image is added to the data storage, the application freezes (mitkAbstractFileReader.cpp:125).
Description
Revisions and Commits
rMITK MITK | |||
Restricted Differential Revision | rMITKf77bc512c1f3 Check if an image contains any valid pixel value at all | ||
Restricted Differential Revision | rMITK00ef843ff8d9 Extend the search for appropriate level window values to other time steps | ||
Restricted Differential Revision | rMITK1de260a7c1a9 Remove unused typedef | ||
Restricted Differential Revision | rMITK570c0df8de3a Improve variable name | ||
Restricted Differential Revision | rMITKb226db94d9e8 Improve readability | ||
Restricted Differential Revision | rMITK31d3c0df98b6 Fix handling of images with NaN pixel values |
Related Objects
- Mentioned In
- T30503: 2024 Week 32 (Early August)
Event Timeline
The freeze happens at the end of QmitkSliderLevelWindowWidget::resizeEvent() or QmitkSliderLevelWindowWidget::Update() resp. QWidget::repaint() but we need to install the debug files of Qt (Qt6Widgetsd.pdb) for further investigation.
The problem is in QmitkSliderLevelWindowWidget::paintEvent.
The example data lead to a level window range that 2*10^300 and that is why the painting takes for ages because it iterates exhaustively and it does not make realy sense.
Sounds like a default value initialized with max possible value and the assumption that it would always be set to the actual value later on? How did you step into QmitkSliderLevelWindowWidget::paintEvent()? I always get stuck right before in Qt6Widgets.
"Empty time steps" turn out be be represented by frames filled with NaN (double). And I think this is the issue. Here's the file were I replaced all NaNs with 0s:
The origin of the huge level window range is the calculation of the image statistics in mitkImageStatisticsHolder.cpp:100. The function template mitk::_ComputeExtremaInItkImage() is supposed to calculate the extrema and 2nd largest/smallest extrema as well as their counts. However, it does not check for NaN and compares it against the default values (itk::NumericTraits<>::max() resp. NonpositiveMin()). Hence, these extrema stay at their initial default values.
How would we like to handle the situation?
- I guess we should check for NaN for each pixel value and skip it.
- Probably track if any valid value was found at all during the pixel iteration.
- Change the statistics values in this case? Check in level window for max()? and NonpositiveMin() and use a predefined "maximum maximum" and a "minimum minimum"? I think there's already a smallest possible value used in the level window like 1e-9.
I think I found an adequate solution:
- Track in statistics calculation if any valid value has been found
- If it's not the case, set min and max to the same value, which is already explicitly handled as edge case appropriately
- Extend the heuristic in LevelWindow::SetAuto() by another cascade, i.e. after the central slice didn't lead to a result, the whole image at time step 0 is already checked, and now: if this also fails the time steps are iterated to search for valid values