QIICR / dcmqi

dcmqi (DICOM for Quantitative Imaging) is a free, open source C++ library for conversion between imaging research formats and the standard DICOM representation for image analysis results
https://qiicr.gitbook.io/dcmqi-guide/
BSD 3-Clause "New" or "Revised" License
228 stars 62 forks source link

Overlapping frames on segimage2itkimage #462

Closed matteo-bastico closed 8 months ago

matteo-bastico commented 1 year ago

I am trying to convert to NIfTI the DICOM segmentation storage of the CTPEL dataset (https://datahub.aida.scilifelab.se/10.23698/aida/ctpel).

The original CT volume shapes are 512 x 512 x 520 but the resulting NIfTIs do not have the same size. I guess it is due to the "overlapping frames" found by segimage2itkimage as shown below.

dcmqi repository URL: git@github.com:QIICR/dcmqi.git revision: 1153738 tag: v1.2.5 Row direction: 1 0 0 Col direction: 0 1 0 Z direction: 0 0 1 Total frames: 844 Total frames with unique IPP: 253 Total overlapping frames: 250 Origin: [-160, -4, -833.6]

What does it mean? How can I obtain in output the same shape of the input?

Moreover, I get 5 different NIfTI files (one per segmentation class), is it possible to have directly an unique file or I have to merge them in post-processing?

Thank you for your help!

fedorov commented 1 year ago

The original CT volume shapes are 512 x 512 x 520 but the resulting NIfTIs do not have the same size. I guess it is due to the "overlapping frames" found by segimage2itkimage as shown below.

This is most likely due to empty slices being skipped during conversion (ie, only those slices that have segmentations are saved in SEG). Because of this, there is no information about the geometry of the original CT volume, and it is not possible to save segmentation as a volume with that geometry.

What does it mean? How can I obtain in output the same shape of the input?

I understand it's an extra step and it is inconvenient, but if you do have access to the source CT, you can simply resample the segmentations to match the geometry of that CT volume.

Moreover, I get 5 different NIfTI files (one per segmentation class), is it possible to have directly an unique file or I have to merge them in post-processing?

You are not the first to ask about this feature, but it is not possible right now. Each segment is saved into a separate volume, because in the general case, segments can overlap. If you need a single NIfTI, at the moment, you will have to check them for overlap, and merge into a single volume.

fedorov commented 1 year ago

I spent some time looking into this, and given current experience with large SEGs, it will be important to add support for this type of output. Saving all segments into a single volume can lead to ~7x performance improvements. Changes to the code to write a single image file are easy, but I will need to spend a bit more time to adjust JSON output to account for this organization.

diff --git a/libsrc/ImageSEGConverter.cpp b/libsrc/ImageSEGConverter.cpp
index 3e8bf99..5b8dd85 100644
--- a/libsrc/ImageSEGConverter.cpp
+++ b/libsrc/ImageSEGConverter.cpp
@@ -596,12 +596,15 @@ namespace dcmqi {
           OFstatic_cast(FGSegmentation*,fgInterface.get(frameId, DcmFGTypes::EFG_SEGMENTATION, isPerFrame));
       assert(fgseg);

-      Uint16 segmentId = -1;
+      Uint16 segmentId = -1, segmentIdLabel;
       if(fgseg->getReferencedSegmentNumber(segmentId).bad()){
         cerr << "ERROR: Failed to get ReferencedSegmentNumber!";
         throw -1;
       }

+      segmentIdLabel = segmentId;
+      segmentId = 1;
+
       // WARNING: this is needed only for David's example, which numbers
       // (incorrectly!) segments starting from 0, should start from 1
       if(segmentId == 0){
@@ -766,7 +769,7 @@ namespace dcmqi {
             index[0] = col;
             index[1] = row;
             index[2] = slice;
-            segment2image[segmentId]->SetPixel(index, segmentId);
+            segment2image[segmentId]->SetPixel(index, segmentIdLabel);
           }
         }
       }
fedorov commented 1 year ago

ITK v5 upgrade has been completed in #444, and this task is next up in the priority list.

Related discussion in https://discourse.slicer.org/t/how-to-export-totalsegmentator-results-as-dicom-seg/27229/6.

I am thinking to implement the following logic:

One question is what to do with the option that allows the user to choose output format. Maybe when output format is not NRRD, when overlapping segments are encountered, output will always be saved as one segment per file?

fedorov commented 8 months ago

This took a while, since this was a non-trivial amount of work, but thanks to the efforts of @michaelonken this feature is now merged, and should be available in the next latest binary of dcmqi. You will need to use the flag --mergeSegments for segimage2itkimage converter. @matteo-bastico let us know if you have any feedback!