Pyradiomics: Warum kommt es zu einer Nichtübereinstimmung der Geometrie, wenn Maske und Bild aus derselben DICOM-Serie stammen?

Erstellt am 23. Apr. 2019  ·  13Kommentare  ·  Quelle: AIM-Harvard/pyradiomics

Hallo,

Für den Kontext konnte ich PyRadiomics erfolgreich über die Befehlszeile ausführen, sowohl für einzelne Bildmaskenpaare als auch für die Stapelextraktion für Dutzende von Bildmaskenpaaren gleichzeitig mit verschiedenen YAML-Konfigurationen. Ich bin jedoch auf ein Problem gestoßen, das ich umgehen kann, aber ich bin immer noch neugierig, warum es auftritt.

Das Setup: Ich habe eine DICOM-Serie für einen Patienten mit 158 ​​Schnitten mit einer Größe von jeweils 512 x 512 Pixel. Ich habe die Serie in Slicer geladen, einen ROI (Knoten) konturiert und dann die binäre Label-Map als .nrrd-Datei exportiert. Dann habe ich das Befehlszeilentool dcm2niix verwendet, um dieselbe DICOM-Serie in ein .nii-Volume zu konvertieren.

Wenn ich Pyradiomics vom Terminal aus mit dem .nii-Bild und der .nrrd-Maske ausführe, erhalte ich eine Geometrie-Nichtübereinstimmung, wie unten beschrieben. Warum würde dies auftreten, wenn die Maske und das Bildvolumen aus derselben DICOM-Serie stammen würden? Ist dies ein erwartetes Ereignis?

Wie bereits erwähnt, gibt es zwei Lösungen: (1) Speichern Sie das Bild als .nii- oder .nrrd-Volume direkt von Slicer, und dies scheint gut zu funktionieren. (2) Passen Sie den Toleranzwert an (obwohl ich mich bei dieser Lösung unwohl fühle). Schließlich möchte ich eine Stapelkonvertierung von Hunderten von DICOM-Serien in .nii- oder .nrrd-Volumes durchführen, und ich habe bereits Masken für diese Hunderte von Serien. Ich hatte gehofft, anstelle von Slicer ein Befehlszeilentool für die Stapelkonvertierung von dcm >> nii oder nrrd verwenden zu können.

Danke für deine Hilfe.

[2019-04-23 16:38:19] E: radiomics.script: Feature extraction failed!
Traceback (most recent call last):
  File "/anaconda3/lib/python3.6/site-packages/pyradiomics-0+unknown-py3.6-macosx-10.7-x86_64.egg/radiomics/imageoperations.py", line 192, in checkMask
    lsif.Execute(imageNode, maskNode)
  File "/anaconda3/lib/python3.6/site-packages/SimpleITK/SimpleITK.py", line 43958, in Execute
    return _SimpleITK.LabelStatisticsImageFilter_Execute(self, *args)
RuntimeError: Exception thrown in SimpleITK LabelStatisticsImageFilter_Execute: /scratch/dashboard/SimpleITK-OSX10.6-x86_64-pkg/SimpleITK-build/ITK-prefix/include/ITK-4.13/itkImageToImageFilter.hxx:241:
itk::ERROR: LabelStatisticsImageFilter(0x7fcd1e601050): Inputs do not occupy the same physical space! 
InputImage Origin: [-1.8200000e+02, 1.6933569e+02, -3.0314999e+02], InputImage_1 Origin: [-1.8200000e+02, -1.7000000e+02, -3.0314999e+02]
    Tolerance: 6.6406202e-07
InputImage Direction: 1.0000000e+00 0.0000000e+00 0.0000000e+00
0.0000000e+00 -1.0000000e+00 0.0000000e+00
0.0000000e+00 0.0000000e+00 1.0000000e+00
, InputImage_1 Direction: 1.0000000e+00 0.0000000e+00 0.0000000e+00
0.0000000e+00 1.0000000e+00 0.0000000e+00
0.0000000e+00 0.0000000e+00 1.0000000e+00

    Tolerance: 1.0000000e-06


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/anaconda3/lib/python3.6/site-packages/pyradiomics-0+unknown-py3.6-macosx-10.7-x86_64.egg/radiomics/scripts/segment.py", line 40, in extractSegment
    feature_vector.update(extractor.execute(imageFilepath, maskFilepath, label))
  File "/anaconda3/lib/python3.6/site-packages/pyradiomics-0+unknown-py3.6-macosx-10.7-x86_64.egg/radiomics/featureextractor.py", line 397, in execute
    boundingBox, correctedMask = imageoperations.checkMask(image, mask, **self.settings)
  File "/anaconda3/lib/python3.6/site-packages/pyradiomics-0+unknown-py3.6-macosx-10.7-x86_64.egg/radiomics/imageoperations.py", line 207, in checkMask
    raise ValueError('Image/Mask geometry mismatch. Potential fix: increase tolerance using geometryTolerance, '
ValueError: Image/Mask geometry mismatch. Potential fix: increase tolerance using geometryTolerance, see Documentation:Usage:Customizing the Extraction:Settings:geometryTolerance for more information
question

Alle 13 Kommentare

Dies liegt daran, dass die Standardtoleranz zu streng ist. Am einfachsten wäre es, das Resampling zu aktivieren.

@warkentinmatt Möglicherweise kann das correctMask behoben werden. Dies ermöglicht ein erneutes Abtasten der Maske (nächster Nachbar), ohne das Bild erneut abzutasten. Die einzige Voraussetzung ist, dass der physische Raum der Maske im Bild enthalten ist.

Was ich vermute, ist, dass Ihre Maske den gleichen Abstand / die gleiche Richtung wie das Bild hat, aber Größe und Ursprung unterschiedlich sind, da Slicer jetzt die Maske speichert, indem der Bereich zugeschnitten und der Ursprung entsprechend angepasst wird. Dies spart Speicherplatz, erfordert jedoch, dass Sie PyRadiomics mitteilen, dass das erneute Abtasten von Masken in Ordnung ist (in diesem letzteren Fall entspricht dies nur dem Auffüllen, bis es der Bildgröße entspricht).

PyRadiomics korrigiert die Maske standardmäßig nicht, da dies als Warnung für den zusätzlichen Schritt dient, den PyRadiomics ausführt.

Vielen Dank für Ihre Antworten.

@JoostJM Um sicherzustellen, dass ich Ihre Kommentare verstehe, schneidet Slicer beim Exportieren / Speichern einer NRRD-Etikettenkarte die Größe auf das Ausmaß des ROI ab? Es behält nicht die ursprüngliche Dimensionalität des Eingangsvolumens bei? Wenn ich die Szene in Slicer lösche, die DICOM-Serie erneut importiere und dann die NRRD-Maske lade, wird die Maske an der richtigen anatomischen Stelle dem CT überlagert. Für mich bedeutete dies, dass die ursprünglichen Abmessungen des CT in der Maske beibehalten wurden. Ist Slicer gerade klug genug (dh mit den richtigen Metadaten), um die Maske auf dem CT richtig auszurichten?

Nur damit ich mir darüber im Klaren bin, was mit dem Resampling der Binärmaske erreicht wird: Mein Verständnis ist, dass, wenn sich der ROI zentral im Bild befindet (daher enthält die Mitte des Arrays einige hunderttausend "Einsen"), dieses Resampling Die nächsten Nachbarn der Maske am Rand des Volumens füllen die Maske im Wesentlichen mit Nullen auf. Ist das eine korrekte Interpretation?

Danke für deine Hilfe.

Nur um sicherzustellen, dass ich Ihre Kommentare verstehe, schneidet Slicer beim Exportieren / Speichern einer NRRD-Etikettenkarte die Größe auf das Ausmaß des ROI ab?

Ja, dies ist möglich, da Nrrd-Dateien auch den Ursprung enthalten, dh den physischen Speicherort des ersten Voxels.
Nrrd enthält auch Informationen zu Richtung und Abstand, sodass Sie auch Segmentierungen überlappen können, die auf Bildern mit unterschiedlichen Pixelgrößen oder sogar solchen, die gedreht werden, erstellt wurden.
Dies ist auch der Grund, warum Numpy-Arrays nicht als Eingabe für PyRadiomics akzeptiert werden, da diese diese geometrischen Informationen nicht enthalten

Nur damit ich mir darüber im Klaren bin, was mit dem Resampling der Binärmaske erreicht wird: Mein Verständnis ist, dass, wenn sich der ROI zentral im Bild befindet (daher enthält die Mitte des Arrays einige hunderttausend "Einsen"), dieses Resampling Die nächsten Nachbarn der Maske am Rand des Volumens füllen die Maske im Wesentlichen mit Nullen auf. Ist das eine korrekte Interpretation?

Richtig

Wenn ich die Szene in Slicer lösche, die DICOM-Serie erneut importiere und dann die NRRD-Maske lade, wird die Maske an der richtigen anatomischen Stelle dem CT überlagert. Für mich bedeutete dies, dass die ursprünglichen Abmessungen des CT in der Maske beibehalten wurden. Ist Slicer gerade klug genug (dh mit den richtigen Metadaten), um die Maske auf dem CT richtig auszurichten?

Die Maske kann einem Teilbereich des Bildes von der Größe des Maskenbegrenzungsrahmens entsprechen. Es muss nicht die gleichen Abmessungen wie das Bild haben. Ob die Abmessungen übereinstimmen oder nicht, hängt davon ab, wie Sie die Segmentierung in Slicer erstellen und wie Sie sie exportieren. Wenn Sie weitere Informationen zur Übereinstimmung der Abmessungen wünschen, teilen Sie uns dies mit.

Wenn ich den Fehler noch einmal betrachte (als ich zum ersten Mal nur einen Blick auf das Telefon geworfen habe), sind hier die Unterschiede:

InputImage Origin: [-1.8200000e+02, 1.6933569e+02, -3.0314999e+02], 
InputImage_1 Origin: [-1.8200000e+02, -1.7000000e+02, -3.0314999e+02]
    Tolerance: 6.6406202e-07

InputImage Direction: 1.0000000e+00 0.0000000e+00 0.0000000e+00
0.0000000e+00 -1.0000000e+00 0.0000000e+00
0.0000000e+00 0.0000000e+00 1.0000000e+00
, 

InputImage_1 Direction: 1.0000000e+00 0.0000000e+00 0.0000000e+00
0.0000000e+00 1.0000000e+00 0.0000000e+00
0.0000000e+00 0.0000000e+00 1.0000000e+00

Sie haben also die Situation, dass der absolute Ursprungswert geringfügig abweicht (und der Unterschied größer als die Standardtoleranz ist), aber auch, dass die Ausrichtung eines Bildes im Vergleich zum anderen in Y umgedreht wird. Dies bedeutet, dass Sie das Problem nicht durch Verringern der Toleranz beheben können und entweder die Maske oder das Bild neu abtasten müssen. Dieses Resampling sollte die Pixelwerte jedoch nicht verändern, es wird effektiv eine Neuorientierungsoperation sein.

@ JoostJM Nochmals vielen Dank für Ihre Antwort, sehr geschätzt.

@fedorov Wie würde ein

Wenn Sie weitere Informationen zur Übereinstimmung der Abmessungen wünschen, teilen Sie uns dies mit.

Ja, ich würde gerne mehr Informationen darüber erhalten, wie Sie sicherstellen können, dass die Abmessungen übereinstimmen. Bitte und Danke.

Tatsächlich würde ich alle Informationen oder Ressourcen lieben, die mein Verständnis einiger dieser von uns diskutierten Konzepte (z. B. Abstand, Richtung, Herkunft) verbessern könnten. Naiv könnte ich denken, dass der Ursprung für ein Bild die [x, y, z] -Koordinaten von [0,0,0] sind, mit anderen Worten, eine der "Ecken" (rechts anterior superior?) Eines Bildarrays . Haben die im Protokoll angezeigten Ursprungswerte eine greifbare Interpretation (z. B. Millimeter oder so)? Was bedeuten diese Zahlen? Verzeihen Sie meine Unwissenheit, ich bin Autodidakt in allen Bereichen der Bildgebung / Radiomik, aber ich möchte diese Konzepte verstehen und nicht nur Lösungen implementieren, damit die Dinge funktionieren.

@warkentinmatt keine Sorge um alle Fragen, es ist eine steile Kurve für einen Anfänger!

Wie würde ein erneutes Abtasten der Maske oder des Bildes das Problem lösen, dass Y relativ zum anderen umgedreht wird?

Bildrichtungen sind im Wesentlichen eine Transformation, die das Koordinatensystem des Bildarrays (IJK) in den anatomischen Raum (XYZ) dreht.

In einem einfachen 1D-Beispiel unten ist "Array-Index" das Koordinatensystem Ihres 1d-Arrays und Links-Rechts das Koordinatensystem im physischen Raum einer 1d-Welt. In Bild 2 ist die Reihenfolge der Werte im Array entgegengesetzt zur Richtung der Achse des physikalischen Koordinatensystems, dh das Array der Voxel ist unterschiedlich ausgerichtet. Beim Resampling wird die Geometrie eines Bildes verwendet, die durch die Arraygröße, -richtung und -ursprung definiert ist, und es werden Werte aus einem anderen Bild an den Voxeln der Referenzgeometrie abgetastet.

image

Macht das Sinn?

Wenn Sie weitere Informationen darüber wünschen, wie Sie sicherstellen können, dass die Abmessungen beim Exportieren des Etiketts aus 3D Slicer übereinstimmen, teilen Sie uns dies mit.
Ja, ich würde gerne mehr Informationen darüber erhalten, wie Sie sicherstellen können, dass die Abmessungen übereinstimmen. Bitte und Danke.

In der Abbildung unten sehen Sie, wie Sie ein Segment aus 3D Slicer in eine Labelmap exportieren (die effektiv ein Binärbild ist). Beachten Sie, dass selbst wenn Sie dieses Verfahren befolgen, es nicht unmöglich ist, dass die Geometrie nicht übereinstimmt, da die Standardtoleranzwerte zu streng sind. Die Ausrichtung des Bildarrays sollte jedoch gleich sein.

image

Tatsächlich würde ich alle Informationen oder Ressourcen lieben, die mein Verständnis einiger dieser von uns diskutierten Konzepte (z. B. Abstand, Richtung, Herkunft) verbessern könnten. Naiv könnte ich denken, dass der Ursprung für ein Bild die [x, y, z] -Koordinaten von [0,0,0] sind, mit anderen Worten, eine der "Ecken" (rechts anterior superior?) Eines Bildarrays . Haben die im Protokoll angezeigten Ursprungswerte eine greifbare Interpretation (z. B. Millimeter oder so)? Was bedeuten diese Zahlen? Verzeihen Sie meine Unwissenheit, ich bin Autodidakt in allen Bereichen der Bildgebung / Radiomik, aber ich möchte diese Konzepte verstehen und nicht nur Lösungen implementieren, damit die Dinge funktionieren.

Hier sind einige Ressourcen, die nützlich sein könnten:

Hoffe das hilft!

@fedorov Vielen Dank, dass Sie sich die Zeit genommen haben, diese Konzepte zu erklären. Das war sehr hilfreich. Es macht viel mehr Sinn und ich schätze Ihre Geduld.

Daher scheint mir das Resampling zwei wichtige, aber unterschiedliche Rollen zu haben, um die geometrische Ausrichtung zwischen zwei Volumes sicherzustellen:

1) Füllen Sie bei Bedarf zunächst das kleinere Volumen auf, bis es der gleichen Größe / Dimension des Referenzvolumens entspricht, und verwenden Sie dabei so etwas wie die nächsten Nachbarn.

2) Sobald die Größe übereinstimmt, verwenden Sie die Informationen zu Ursprung, Richtung und Abstand, um die Voxel so abzutasten, dass sichergestellt ist, dass zwei Volumina, die sich in anatomischer / physischer Ausrichtung befinden, ebenfalls auf dieselbe Weise indiziert werden (dh Array-Indexausrichtung) ).

Wäre dies eine faire Zusammenfassung der Rolle des Resamplings?

Vielen Dank auch für das Teilen dieser Ressourcen. Ich freue mich darauf, sie durchzuarbeiten, um mein Verständnis zu stärken.

@warkentinmatt , fast. Die Schritte 1 und 2 werden gleichzeitig ausgeführt. Was passiert, ist, dass Sie ein Raster von Punkten im physischen Raum definieren und dann Ihr Bild an diesen Punkten abtasten. Wenn die neuen Gitterpunkte nicht genau mit den vorhandenen Gitterpunkten übereinstimmen, werden neue Werte mithilfe des Interpolationsalgorithmus basierend auf den umgebenden (ursprünglichen) Punkten (Pixeln) des Bildes berechnet.

Eine ausführliche Erklärung finden Sie auch in den IBSI-Dokumenten, Abschnitt zur Interpolation . Dieses enthält auch ein Bild, das das Resampling-Gitter darstellt.

@fedorov @JoostJM Ich weiß, dass dieses Problem geschlossen ist, und ich bin zutiefst dankbar für die Hilfe, die Sie beide geleistet haben. Ich wollte nur zurückkreisen, um mein Verständnis zu klären. Nachdem ich die von Ihnen bereitgestellten Ressourcen gründlich durchgelesen und einige hilfreiche Videos angesehen habe, bin ich mit diesen Konzepten viel zufriedener.

In dem Beispiel, in dem dieses Problem aufgetreten ist, war der Abstand derselbe, da die Maske von demselben Bild abgeleitet wurde, das für die Merkmalsextraktion verwendet wurde. Mit anderen Worten, eine Änderung der Voxelposition um eine Einheit in einer der x-, y- und z-Richtungen für die Maske oder das Bild führt zur gleichen Interpretation der physikalischen Änderung. In Fällen, in denen der Abstand zwischen Maske und Bild gleich ist, wäre keine Interpolation erforderlich, um "die Lücken zu füllen", richtig? Ein erneutes Abtasten der Maske würde also einfach eine geometrische Übereinstimmung mit dem Bild in Bezug auf beide Dimensionen des Volumens sicherstellen sowie sicherstellen, dass beide Volumina, die sich in physischer Ausrichtung befinden, auf dieselbe Weise (in Bezug auf Richtung und Ursprung) auch Array-indiziert werden ). Habe ich das endlich richtig verstanden?

Wenn der Abstand zwischen zwei Volumes nicht gleich wäre, müssten Sie Voxel interpolieren, um zwei Volumes in geometrischer Ausrichtung zu erhalten. Wenn beispielsweise der Bildabstand [1 mm, 1 mm, 1 mm] und die Maske [2 mm, 2 mm, 2 mm] betrug, müssten Sie Voxel in der Maske interpolieren, um die Lücken im physischen Abstand zu füllen.

Nochmals danke für all deine Hilfe. Es hat den Unterschied gemacht.

@warkentinmatt ja, das macht Sinn, ich denke du hast es richtig gemacht!

Eine weitere nützliche Ressource im Zusammenhang mit Resampling ist diese Seite: https://www.slicer.org/wiki/Registration : Resampling

@ Fedorov Großartig. Nochmals danke für all deine Hilfe.

Dies ist möglicherweise nicht die Zeit oder der Ort, aber nach meinem Verständnis haben Sie Ihren Sitz außerhalb von Boston. Derzeit bin ich Doktorand in Toronto, aber ich ziehe nach Boston, um zwei Wochen für ein Forschungsstipendium in der Abteilung für Biostatistik am HSPH zu arbeiten. Ich würde mich gerne persönlich verbinden und vielleicht einige dieser Gespräche fortsetzen, wenn Sie überhaupt interessiert wären und die Zeit dazu hätten. In jedem Fall wurde Ihre Hilfe sehr geschätzt.

Sicher, gerne verbinden und mehr darüber erfahren, wie Sie Pyradiomics verwenden! Schicken Sie mir einfach eine E-Mail (es ist öffentlich in meinem Github-Profil), und wir können uns zum Kaffee treffen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen