donderdag 24 december 2015

MRI - 02 - Data schonen

Nadat de probleemstelling ongeveer duidelijk is geworden (behalve nog de vorm van de uiteindelijke 'submission' - kom ik later op terug) een even een strategie bedenken. Waarschijnlijk iets met convolutional neural networks. Het betreft tenslotte afbeeldingen. De bepaling van de beste slices en daarin het juiste systolisch en diastolisch moment zal echter alleen al lastig zijn. Daarna moet de relatie met de volumes nog worden gelegd.


Voordat ik echter daaraan toe ben eerst maar eens zien of ik de data kan 'schonen' en 'normaliseren'. Het eerste gaat vooral om het verwijderen van ruis en overbodige informatie. Het tweede gaat erom dat de afbeeldingen een vergelijkbare intensiteit hebben, dezelfde pixel nauwkeurigheid (8/16 bits) en bijvoorbeeld even groot zijn. Tevens wil ik dat ze eenzelfde schaal gebruiken. Dezelfde hoeveelheid pixels per mm.

Dankzij de module pydicom kan ik de dicom afbeeldingen in Python inlezen. Ook de metadata blijkt geen probleem.

import numpy

import dicom
ds = dicom.read_file('IM-7310-0001.dcm')
di = ds.pixel_array                       # afbeelding in numpy array laden
print ds.PatientAge, ds.Rows, ds.Columns, ds.PixelSpacing[0]

De studies zitten in een diepe directory structuur. Gelukkig heeft de Python 'os-module' daar een charmante oplossing voor. Ik zorg gelijk dat ik 'random' 'sax' (short axis) bestanden kan selecteren:

for root, dirs, files in os.walk(RootDir):
    ra = random.random()
    if ra < .005 and "sax" in root:
        print '******************************'
        print root
        for name in files:
            if ".dcm" in name:

                ds = dicom.read_file(os.path.join(root, name))

Voor weergave gebruik ik de OpenCV module. Ik verwacht meerdere functies uit die module voor beeldmanipulatie nodig te gaan hebben.  Bijvoorbeeld tonen van pixelarray 'combi':

import cv2
cv2.imshow("combi", combi)
cv2.moveWindow("combi", 100, 150)
cv2.waitKey()


cv2.destroyAllWindows()

Sommige afbeeldingen hebben veel last van 'outliers'. Extreme (grijs) waarden die ver af staan van het gemiddelde. Om te normaliseren wil ik alle afbeeldingspixels naar eenzelfde 'range' toebrengen. Sklearn - preprocessing heeft daar standaard routines voor. Ik probeer 'MinMaxScaler'. Ik krijg echter rare 'artefacten' - strepen over mijn afbeeldingen. Ook bij enkele andere 'scalers' van Scikit verschijnen deze.

Rare strepen bij sklearn pre-processing.
Raar! Ook de RobustScaler, die minder 'outlier-gevoelig is' geeft hetzelfde.  Ik besluit zelf maar een eenvoudige scaler te bouwen. Met het verwijderen van de outliers. De afbeeldingen beginnen nu een beetje met gelijke donkerte op het scherm te komen.:


def NormIm(InIm):              # Verwijder outliers en normalize naar waarde.
    Perc = 95                  # alles boven Perc% wordt op maximum gezet
    Max = 500.
    Percentiel = np.percentile(InIm, Perc)
    h=np.clip(InIm, 0, Percentiel)
    return h * Max / h.max()   # breng alles naar schaal 'Max'  

Een belangrijk deel van het 'data schonen' is ook zoveel mogelijk van de afbeelding wegsnijden dat niet met het hart te maken heeft. Ik ga opzoek naar een manier om dat automatisch te selecteren.


  

Geen opmerkingen:

Een reactie posten