[PYTHON] Mit Pyradiomics erlernte Texturanalyse

pyradiomics

Sie können solche Bildmerkmale berechnen.

Für Bilder eindimensionaler quantitativer Wert "erster Ordnung" ~~ (enthält aber auch Merkmale, die sich fragen, ob er als eindimensional interpretiert werden sollte) ~~, Form, um die Form wie rund oder gezackt von Pixeln zu analysieren Es ist eine Bibliothek, die GLCM usw. analysieren kann, um das Anordnungsmuster zu untersuchen. Teile wie GLCM sind zur Beschleunigung in der Sprache C geschrieben. Wenn Sie dies als Python-Objekt bezeichnen, wird die Berechnungsgeschwindigkeit erhöht.

Einsatzbereit

Es wurde von einem Forscher erstellt, ist also sehr einfach und kann schnell in eine CSV-Tabelle umgewandelt werden. Hier schreibe ich bis zu dem Punkt, an dem das Berechnungsergebnis angezeigt wird.

Umgebung

Google colaboratory

Verfahren

Installieren Sie zunächst die Bibliothek vorübergehend.

!pip install pyradiomics

Sie können es so installieren.

Collecting pyradiomics
  Downloading https://files.pythonhosted.org/packages/1d/6b/797d3fd59e16675f6d8fa3ad0f778a025e06bcb1fd595439d43aff0a522e/pyradiomics-2.2.0-cp36-cp36m-manylinux1_x86_64.whl (159kB)
     |████████████████████████████████| 163kB 2.8MB/s 
Collecting pykwalify>=1.6.0
  Downloading https://files.pythonhosted.org/packages/36/9f/612de8ca540bd24d604f544248c4c46e9db76f6ea5eb75fb4244da6ebbf0/pykwalify-1.7.0-py2.py3-none-any.whl (40kB)
     |████████████████████████████████| 40kB 5.4MB/s 
Requirement already satisfied: numpy>=1.9.2 in /usr/local/lib/python3.6/dist-packages (from pyradiomics) (1.17.3)
Collecting SimpleITK>=0.9.1
  Downloading https://files.pythonhosted.org/packages/bb/06/f3a67ef0e108d18840fd5e83f831d5ef1710ba46f05465fc50f9a505b518/SimpleITK-1.2.3-cp36-cp36m-manylinux1_x86_64.whl (42.5MB)
     |████████████████████████████████| 42.5MB 54kB/s 
Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from pyradiomics) (1.12.0)
Collecting PyWavelets<=1.0.0,>=0.4.0
  Downloading https://files.pythonhosted.org/packages/90/d0/09b2bf3368d5bba6ee1a8868ce94eebbb105fc8bf89fa43c90348b21a7cb/PyWavelets-1.0.0-cp36-cp36m-manylinux1_x86_64.whl (4.4MB)
     |████████████████████████████████| 4.4MB 35.8MB/s 
Requirement already satisfied: PyYAML>=3.11 in /usr/local/lib/python3.6/dist-packages (from pykwalify>=1.6.0->pyradiomics) (3.13)
Requirement already satisfied: docopt>=0.6.2 in /usr/local/lib/python3.6/dist-packages (from pykwalify>=1.6.0->pyradiomics) (0.6.2)
Requirement already satisfied: python-dateutil>=2.4.2 in /usr/local/lib/python3.6/dist-packages (from pykwalify>=1.6.0->pyradiomics) (2.6.1)
ERROR: albumentations 0.1.12 has requirement imgaug<0.2.7,>=0.2.5, but you'll have imgaug 0.2.9 which is incompatible.
Installing collected packages: pykwalify, SimpleITK, PyWavelets, pyradiomics
  Found existing installation: PyWavelets 1.1.1
    Uninstalling PyWavelets-1.1.1:
      Successfully uninstalled PyWavelets-1.1.1
Successfully installed PyWavelets-1.0.0 SimpleITK-1.2.3 pykwalify-1.7.0 pyradiomics-2.2.0

(Im Moment erhalte ich die Fehlermeldung, dass Sie die niedrigere Version von imgaug verwenden sollten, diese aber ignorieren sollten.)

Importieren Sie die erforderlichen Funktionen.

import os  # needed navigate the system to get the input data
from radiomics import featureextractor  # This module is used for interaction with pyradiomics
import radiomics
from radiomics import firstorder, getTestCase, glcm, glrlm, glszm, imageoperations, shape, shape2D
import numpy as np
import six

#http://simpleitk.github.io/SimpleITK-Notebooks/01_Image_Basics.html
import SimpleITK as sitk
import matplotlib.pyplot as plt

Wir werden die von pyradiomics bereitgestellten Testdaten verwenden. Das Bildformat ist das Bild im Nrrd-Format, das häufig im 3D-Bildverarbeitungsbereich (3DSlicer) verwendet wird. Sie können die SimpleITK-Bibliothek zum Laden verwenden. Es kann verschiedene Bildformate unterstützen. Auch wenn Nrrd nicht verfügbar ist, können Sie es durch tiff oder png ersetzen. (Wenn Sie Dicom verwenden, können Sie es mit pydicom in NDArray konvertieren und dann als einfaches ITK-Image konvertieren.) (https://github.com/Radiomics/pyradiomics/issues/339) Verwenden wir die Probe "lung2".

# brain1, brain2, breast1, lung1,lung2,(prostate_phantom)
# brain,1,2 hat möglicherweise die falsche Maske (kein Beschriftungsbereich)?
imageName, maskName = getTestCase('lung2')
image = sitk.ReadImage(imageName)
mask = sitk.ReadImage(maskName)

Wenn Sie ein Bild in einem gängigen Format (z. B. tif) in Ihre Colab-Notiz hochgeladen haben, gehen Sie folgendermaßen vor:

#Rufen Sie aus der Datei von colab auf (Beispiel: Angenommen, sie befindet sich im übergeordneten Verzeichnis).
# imagePath = os.path.join(os.getcwd(), "lung2" + "_image.tif")
# maskPath = os.path.join(os.getcwd(), "lung2" + "_label.tif")
# image = sitk.ReadImage(imagePath)
# mask = sitk.ReadImage(maskPath)

Stellen Sie sicher, dass es richtig geladen wird. (Das Schneiden kann wie folgt sein, aber beachten Sie, dass die Pixelsequenz numpy.adarray (h, w) für itkImage (w, y) ist.)

ndImg = sitk.GetArrayFromImage(image)
ndLbl = sitk.GetArrayFromImage(mask)
plt.imshow(ndImg[24])
plt.show()
plt.imshow(ndLbl[24])
plt.show()

ダウンロード.png ダウンロード (1).png

Diese Daten sind 3D-Daten. Weil die 2D-Bilder in Richtung der Z-Achse ausgerichtet sind. Ich persönlich denke, dass Pyradiomics von Anfang an 3D-Berechnungen durchführen soll.

Erstellen Sie eine Einstellungsdatei. Hier ist es einfach, aber standardmäßig.

settings = {}
settings['binWidth'] = 25
# If enabled, resample image (resampled image is automatically cropped.
settings['resampledPixelSpacing'] = None  # [3,3,3] is an example for defining resampling (voxels with size 3x3x3mm)
settings['interpolator'] = sitk.sitkBSpline
settings['label'] = 1 #Weil der Maskenbereich einen Pixelwert von 1 hat (andernfalls ist er 0).

Schneiden Sie den Teil der Maske zu. Dies ist ein 2D-Bildsatz nur des Tumorbereichs. (Es ist ein 3D-Volumen.)

#Überprüfen Sie die Integrität der Maske und erstellen Sie eine bbox# 2020/1/23 Nachtrag
bb, correctedMask = imageoperations.checkMask(image, mask)
if correctedMask is not None:
  mask = correctedMask
image, mask = imageoperations.cropToTumorMask(image, mask, bb)

Die Vorbereitung ist abgeschlossen. Führen Sie dann die Berechnung aus.

Berechnen Sie zunächst die eindimensionale Merkmalsmenge aus dem zugeschnittenen Volumen. Es gibt auch den Typ und die Bedeutung aus.

firstOrderFeatures = firstorder.RadiomicsFirstOrder(image, mask, **settings)
# firstOrderFeatures.enableFeatureByName('Mean', True)
firstOrderFeatures.enableAllFeatures()

print('Will calculate the following first order features: ')
for f in firstOrderFeatures.enabledFeatures.keys():
  print('  ', f)
  print(getattr(firstOrderFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating first order features...')
results = firstOrderFeatures.execute()
print('done')

print('Calculated first order features: ')
for (key, val) in six.iteritems(results):
  print('  ', key, ':', val)

Als nächstes sind die Eigenschaften der Form.

shapeFeatures = shape.RadiomicsShape(image, mask, **settings)
shapeFeatures.enableAllFeatures()

print('Will calculate the following Shape features: ')
for f in shapeFeatures.enabledFeatures.keys():
  print('  ', f)
  print(getattr(shapeFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating Shape features...')
results = shapeFeatures.execute()
print('done')

print('Calculated Shape features: ')
for (key, val) in six.iteritems(results):
  print('  ', key, ':', val)

Von hier aus berechnen wir Features wie GLCM.

# Show GLCM features
glcmFeatures = glcm.RadiomicsGLCM(image, mask, **settings)
glcmFeatures.enableAllFeatures()

print('Will calculate the following GLCM features: ')
for f in glcmFeatures.enabledFeatures.keys():
  print('  ', f)
  print(getattr(glcmFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating GLCM features...')
results = glcmFeatures.execute()
print('done')

print('Calculated GLCM features: ')
for (key, val) in six.iteritems(results):
  print('  ', key, ':', val)

# Show GLRLM features
glrlmFeatures = glrlm.RadiomicsGLRLM(image, mask, **settings)
glrlmFeatures.enableAllFeatures()

print('Will calculate the following GLRLM features: ')
for f in glrlmFeatures.enabledFeatures.keys():
  print('  ', f)
  print(getattr(glrlmFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating GLRLM features...')
results = glrlmFeatures.execute()
print('done')

print('Calculated GLRLM features: ')
for (key, val) in six.iteritems(results):
  print('  ', key, ':', val)

# Show GLSZM features
glszmFeatures = glszm.RadiomicsGLSZM(image, mask, **settings)
glszmFeatures.enableAllFeatures()

print('Will calculate the following GLSZM features: ')
for f in glszmFeatures.enabledFeatures.keys():
  print('  ', f)
  print(getattr(glszmFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating GLSZM features...')
results = glszmFeatures.execute()
print('done')

print('Calculated GLSZM features: ')
for (key, val) in six.iteritems(results):
  print('  ', key, ':', val)

#Ich werde es hier schaffen.

Der obige Vorgang kann auch eine 2D-Analyse sein, wenn Sie ein 2D-Bild als Eingabe eingeben. Wenn Sie jedoch von Anfang an wissen, dass es sich um eine 2D-Analyse handelt, können Sie diese wie folgt eingeben. Übergeben Sie nur ein Bild.

# choose 2D array
#Der Speicher wird referenziert und geändert. Rufen Sie ihn daher erneut auf.
imageName, maskName = getTestCase('lung2')
imageStack = sitk.ReadImage(imageName)
maskSatck = sitk.ReadImage(maskName)

#Extrahieren Sie Pixel als Adarray für parametrische Bildberechnungen usw.(Beispiel für die 24. Scheibe)
ndimage = sitk.GetArrayFromImage(imageStack)[24]
ndmask = sitk.GetArrayFromImage(maskStack)[24]

#Grundsätzlich haben die Daten, die ursprünglich ein DICOM-Bild waren, eine Dimension von 3, sodass sie erweitert werden.
ndimage = np.expand_dims(ndimage, axis=0)
ndmask = np.expand_dims(ndmask, axis=0)

print(ndimage.shape)# (1, 512, 512)Auch bei force2D muss die Form 3D sein.
print(ndmask.shape)# (1, 512, 512)

Wenn Sie das Pixel ndarray nach der Berechnung aus verschiedenen Gründen als Sitk-Bild neu zuweisen möchten, tun Sie dies.

image = sitk.GetImageFromArray(ndimage)
mask = sitk.GetImageFromArray(ndmask)

Setzen Sie Informationen wie die Pixelgröße zurück. (Hinzugefügt am 14.11.2019, hinzugefügt am 21.12.2019)

# copy geometric/calibration info
image.CopyInformation(imageStack[:,:,24]) 
mask.CopyInformation(maskStack[:,:,24]) 

#Wenn das Originalbild Metadaten enthält und sich die geometrischen Informationen wie Matrixgröße, Ursprung, Pixelabstand usw. nicht ändern, kopieren Sie alternativ die Metadaten aus den Originaldaten.
#Im Fall von DICOM (obwohl es diesmal schwierig ist) ist es jedoch besser, die Informationen wie die Serien-UID und die Bilderstellungszeit zu aktualisieren.

for i,key in enumerate(imageStack[:,:,24].GetMetaDataKeys()):
        image.SetMetaData(key, imageStack[:,:,24].GetMetaData(key))
for i,key in enumerate(maskStack[:,:,24].GetMetaDataKeys()):
        mask.SetMetaData(key, maskStack[:,:,24].GetMetaData(key))

Fügen Sie in den Einstellungen force2D hinzu.

settings = {}
settings['binWidth'] = 25
# If enabled, resample image (resampled image is automatically cropped.
settings['resampledPixelSpacing'] = None  # [3,3,3] is an example for defining resampling (voxels with size 3x3x3mm)
settings['interpolator'] = sitk.sitkBSpline
settings['label'] = 1
settings['force2D'] = True
settings['correctMask'] = True #Wenn die geometrischen Informationen wie der Ursprung des zu analysierenden Bildes und das Maskenbild unterschiedlich sind, werden sie automatisch angepasst.

Der Rest des Prozesses ist der gleiche, daher wird hier nur die erste Reihenfolge angezeigt.

# Show the first order feature calculations
firstOrderFeatures = firstorder.RadiomicsFirstOrder(image, mask, **settings)
# firstOrderFeatures.enableFeatureByName('Mean', True) #Bei der Angabe eines bestimmten Elements
firstOrderFeatures.enableAllFeatures()

#Auskommentieren, da es sich um ein Duplikat handelt.
# print('Will calculate the following first order features: ')
# for f in firstOrderFeatures.enabledFeatures.keys():
#   print('  ', f)
#   print(getattr(firstOrderFeatures, 'get%sFeatureValue' % f).__doc__)

print('Calculating first order features...')
results = firstOrderFeatures.execute()
print('done')

print('Calculated first order features: ')
for (key, val) in six.iteritems(results):
  print('  ', key, ':', val)

das ist alles.

VisionaryImagingServices, Inc. Tatsuaki Kobayashi

Reference

Recommended Posts

Mit Pyradiomics erlernte Texturanalyse
Datenanalyse mit Python 2
Korbanalyse mit Spark (1)
Abhängigkeitsanalyse mit CaboCha
Sprachanalyse mit Python
Sprachanalyse mit Python
Dynamische Analyse von Valgrind
Führen Sie eine Regressionsanalyse mit NumPy durch
Datenanalyse mit Python
Maschinelles Lernen mit Pokemon gelernt
[Python] Morphologische Analyse mit MeCab
[Analyse des gemeinsamen Auftretens] Einfache Analyse des gemeinsamen Auftretens mit Python! [Python]
Multiple Regressionsanalyse mit Keras
Planare Skelettanalyse mit Python
Japanische morphologische Analyse mit Python
Muskel-Ruck-Analyse mit Python
[PowerShell] Morphologische Analyse mit SudachiPy
Text Emotionsanalyse mit ML-Ask
Impedanzanalyse (EIS) mit Python [impedance.py]
[Python] Mit Pokemon erlernte objektorientierte Programmierung
Hauptkomponentenanalyse mit Spark ML
Perceptron-Lernexperiment mit Python
Python-Datenstruktur mit Chemoinfomatik gelernt
Effiziente Netzaufnahme mit Python
1. Mit Python 1-1 gelernte Statistiken. Grundlegende Statistiken (Pandas)
Bequeme Analyse mit Pandas + Jupyter Notebook
Service Mesh mit Docker Swarm gelernt
Ich habe mit Mecab gespielt (morphologische Analyse)!
Mit OR-Tools Part0 erlernte Optimierung [Einführung]
Datenanalyse beginnend mit Python (Datenvisualisierung 1)
Logistische Regressionsanalyse Selbst erstellt mit Python
Datenanalyse beginnend mit Python (Datenvisualisierung 2)