• Non ci sono risultati.

Ricerca di noduli polmonari in immagini di tomografia computerizzata (CT)

N/A
N/A
Protected

Academic year: 2021

Condividi "Ricerca di noduli polmonari in immagini di tomografia computerizzata (CT)"

Copied!
24
0
0

Testo completo

(1)

Ricerca di noduli polmonari in immagini di tomografia

computerizzata (CT)

(2)

Com’è fatto un nodulo?

• Un nodulo polmonare è una formazione

generalmente compatta, tendenzialmente sferica, di densità media (numero di Hounsfield) paragonabile a quella dell’acqua

• I noduli possono essere classificati in base alla loro posizione nel polmone, in n1, n2, n3

(ATTENZIONE! Classificazione NON standard!):

– n1: nodulo interno

– n2: nodulo cresciuto nelle vicinanze della pleura e ad essa connesso

– n3: nodulo originatosi nella pleura, alla quale è connesso in genere tramite un peduncolo

(3)

Tipologie di noduli polmonari

n 1 n 2 n 3

3

(4)

Esempio…

• Consideriamo una CT: cdPi152_S3

• Il radiologo, operando tramite un software dotato di

interfaccia grafica per la visualizzazione delle fette e la refertazione, costruisce il seguente record di informazioni:

1,45,301,134,3.15,0,n1,NC,SD,PD,T1,ND,ND,504,RadGS,2008-05-15 2,291,382,228,2.52,0,n2,NC,SD,PD,T1,ND,ND,504,RadGS,2008-05-15 3,70,300,255,4.57,0,n2,NC,SD,PD,T1,ND,ND,504,RadGS,2008-05-15 4,102,300,232,5.39,0,n1,ND,ND,ND,ND,ND,ND,504,RadGS,2008-05-15

COORDINATE x, y, z

del centro (z è la slice) “RAGGIO” DEL NODULO (mm)

TIPOLOGIA

n. progressivo

(5)

Immagini 2D dei noduli

1

2

3

4

(6)

Proviamo a visualizzare i noduli!

• Abbiamo bisogno del file contenente il volume della CT (in formato analyze, di cui sfrutteremo i dati raw):

cdPi152_S3_D0.hdr e cdPi152_S3_D0.img

(hdr: header; img: voxel, dimensione file = w x h x d)

• Un file analyze può essere aperto da software free e.g. MRIcro

• Le coordinate indicate in MRIcro (in basso a sx) sono in mm;

per ottenerle, moltiplicare le coordinate qui riportate per il voxel size (mm): [45 301 134] .* [0.63 0.63 1] = [28.35 189.63 134];

• La CT cdPi152_S3_D0 ha dimensioni 512x512x334

• Carichiamo il file nel workspace di MATLAB

(7)

Codice MATLAB per caricare l’immagine e mostrare il nodulo in sezione

% apriamo e leggiamo il file contenente i dati dei voxel, 2 byte/voxel, int16 fid = fopen('cdPi152_S3_D0.img', 'r');

D = fread(fid, 'int16=>int16'); % senza spazi nella stringa!

fclose(fid);

nslices = size(D,1) / (512*512);

% il file e’ una collezione lineare di int16, senza struttura di matrice 3D:

% per ridare la struttura originale, usiamo

% l’istruzione reshape (controllare

% il workspace prima e dopo l’istruzione) D = reshape(D, [512, 512, nslices]);

% visualizziamo una fetta in cui compaia il nodulo imshow(D(:, :, 134)', [])

mostra_nodulo.m

(8)

Visualizzazione del nodulo in 3D (1)

• Esistono diverse modalità di rappresentazione

tridimensionale; la più semplice è la visualizzazione

prospettica di una isosuperficie opportuna della densità (valore di grigio) [il nodulo non è un oggetto immerso nel vuoto!]

• Siccome un nodulo è un oggetto compatto e denso rispetto all’ambiente in cui si sviluppa (il parenchima polmonare), per visualizzare il nodulo in 3D occorre applicare

all’immagine cdPi152_S3_D0 un’operazione di sogliatura (con valore di soglia deciso usando per esempio lo

strumento impixelinfo), ottenendo cdPi152_S3_TH;

• Si evidenziano così nella CT gli oggetti costituiti da voxel densi; la frontiera degli oggetti così definiti (isosuperficie) sarà rappresentata in prospettiva

(9)

• La ricerca dei candidati noduli nella CT si effettua tramite l’operazione bwlabel applicata all’immagine dopo

sogliatura cdPi152_S3_TH

• Per limitare il numero di falsi positivi, è opportuno

preliminarmente segmentare la CT, ossia limitare al solo parenchima polmonare il volume in cui effettuare la

ricerca

• L’operazione di segmentazione (che non sarà qui dettagliata) fornisce in output una maschera

(cdPi152_S3_M4) che delimita il volume polmonare

• Combinando M4 con la CT originale sogliata, per ottenere il solo tessuto polmonare (cdPi152_S3_D2)

Ricerca dei candidati noduli in una CT (0)

(10)

Maschera di segmentazione

(11)

close all, clear

% apriamo e leggiamo il file contenente i dati dei voxel, 2 byte/voxel, int16 fid = fopen('cdPi152_S3_D0.img', 'r');

D = fread(fid, 'int16=>int16');

fclose(fid);

nslices = size(D, 1) / (512*512);

% il file e’ una collezione lineare di int16, senza struttura di matrice 3D:

% per ridare la struttura originale, usiamo l’istruzione reshape (controllare

% il workspace prima e dopo l’istruzione) D = reshape(D, [512, 512, nslices]);

% visualizziamo una fetta in cui compaia il nodulo figure

imshow(D(:, :, 134)', [])

Ricerca dei candidati noduli in una CT (1)

cerca_VOIs.m

(12)

% Ora applichiamo la soglia opportuna (grigio > -300) D = D > -300;

figure

imshow(int8(D(:, :, 134)'), [])

% Prima di cercare gli oggetti connessi, usiamo la matrice

% di segmentazione per limitare lo spazio di ricerca

% (e quindi i falsi positivi e il tempo di calcolo) fid = fopen('cdPi152_S3_M4.img', 'r');

M = fread(fid, 'int8=>int8');

fclose(fid);

M = logical(reshape(M, [512, 512, nslices]));

figure

imshow(M(:, :, 134)', [])

% Operazione di masking (AND logico) D = D & M;

figure

imshow(D(:, :, 134)', [])

Ricerca dei candidati noduli in una CT (2)

cerca_VOIs.m

Soglia individuata tramite pixval; andrebbe trovato un valore buono per TUTTI i noduli, impresa difficile…

(13)

% Cerchiamo oggetti connessi L = bwlabeln(D); % n dimensioni!

figure

imshow(L(:, :, 134)', [])

stats = regionprops(L, 'Area', 'BoundingBox', 'Centroid', 'Image', 'PixelList');

% Filtro sul volume: consideriamo solo oggetti di dimensioni maggiori di 30

% pixel circa (cioe' noduli circa maggiori di 3x3x3 mm) Areas = [stats.Area];

ind = find(Areas > 30);

stats = stats(ind);

% l’oggetto di statistiche stats(1) ha etichetta ind(1) in L

% ordiniamo per volume decrescente

Areas = [stats.Area]; % lo rifaccio perche’ stats e’ cambiato [newAreas, s] = sort(Areas, 'descend');

stats = stats(s);

ind = ind(s);

Ricerca dei candidati noduli in una CT (3)

cerca_VOIs.m

(14)

Come usare il vettore di statistiche

>> stats stats =

219x1 struct array with fields:

Area Centroid BoundingBox Image

PixelList

>> stats(1) ans =

Area: 607327

Centroid: [271.9238 260.5258 175.6243]

BoundingBox: [101.5000 29.5000 19.5000 317 454 291]

Image: [454x317x291 logical]

PixelList: [607327x3 double]

>> stats(130).PixelList ans =

261 230 105 262 230 105 261 226 106 261 227 106 261 228 106 261 229 106 ...

262 213 112 262 214 112 263 210 112 263 211 112

mostra3D(stats(30).Image)

per il codice di mostra3D, vedere le prox slide!

(15)

Quali features scegliere?

• volume = numero di voxel accesi nella roi

• raggio = raggio della sfera più piccola contenente la ROI (sfera circoscritta)

• sfericità = rapporto tra l’area della superficie di una sfera avente volume pari a quello della ROI e l’area della superficie della ROI

DA CALCOLARE DA CALCOLARE

(16)

Sfericità

Wikipedia (http://en.wikipedia.org/wiki/Sphericity)

Sphericity is a measure of how spherical (round) an object is. As such, it is a specific example of a compactness measure of a shape. Defined by

Wadell in 1935, the sphericity, Ψ, of a particle is the ratio of the surface area of a sphere (with the same volume as the given particle) to the surface area of the particle:

where Vp is volume of the particle and Ap is the surface area of the particle

(17)

for n = 1:length(stats)

stats(n).RadiusC = 0.5 * sqrt(stats(n).BoundingBox(4) ^ 2 + \ stats(n).BoundingBox(5) ^ 2 + \ stats(n).BoundingBox(6) ^ 2);

stats(n).Sphericity = stats(n).Area / (4.0/3 * pi * stats(n).RadiusC ^ 3);

end

Ricerca dei candidati noduli in una CT (4)

cerca_VOIs.m

>> stats stats =

219x1 struct array with fields:

Area Centroid BoundingBox Image

PixelList Frontier Surfarea RadiusC Sphericity

(18)

Visualizzazione noduli n1

% individuiamo un nodulo

% sappiamo che il nodulo (1) si trova a 45,301,134,

% ma dobbiamo INVERTIRE x con y!!!

nn = [];

for n = 1:length(stats) c = stats(n).Centroid;

if pdist([301, 45, 134 ; c]) < 10 disp ('Trovato!')

disp (n)

nn = [nn, n];

end end

nn = nn(1);

figure, mostra3D(stats(nn).Image)

cerca_VOIs.m

102, 300, 232 N = 95

N = 41

(19)

cerca_VOIs.m

102, 300, 232

N = 158

291,382,228 nodulo 2 (tipo n2)

Il nodulo 3 (tipo n2) non si distingue 70,300,255

Visualizzazione noduli n2

(20)

mostra3D

function mostra3D(D)

% %%% 3D

%

% figure;

%

% Inseriamo l'oggetto in una matrice un po' piu' grande: ho verificato che

% se non lo si fa, compaiono dei buchi nella isosuperficie laddove essa

% incontra la box s = size(D);

D1 = zeros(s(1) + 4, s(2) + 4, s(3) + 4);

D1(3:3+s(1)-1, 3:3+s(2)-1, 3:3+s(3)-1) = D;

D = D1;

clear D1

D = smooth3(double(D));

hiso = patch(isosurface(D),...

'FaceColor',[1,.75,.65],...

'EdgeColor','none');

view(45,30) axis tight

daspect([1,1,.67]) % il .67 viene da 1/1.5 lightangle(45,30);

set(gcf,'Renderer','zbuffer'); lighting phong isonormals(D,hiso)

%set(hcap,'AmbientStrength',.6)

set(hiso,'SpecularColorReflectance',0,'SpecularExponent',50) box

(21)

VOIs

save stats stats clear

load stats

mostra3D(stats(2).Image)

(22)

Statistiche sui noduli

Nodulo 1 (indice 95)

>> stats(95) ans =

Area: 80

Centroid: [301.9750 46.2250 135.4250]

BoundingBox: [298.5000 43.5000 133.5000 7 6 4]

Image: [6x7x4 logical]

PixelList: [80x3 double]

RadiusC: 5.0249 Sphericity: 0.1505 Nodulo 4 (indice 41)

>> stats(41) ans =

Area: 222

Centroid: [300.3108 102.4324 233.8739]

BoundingBox: [293.5000 95.5000 228.5000 12 12 8]

Image: [12x12x8 logical]

PixelList: [222x3 double]

RadiusC: 9.3808 Sphericity: 0.0642 Nodulo 2 (indice 158)

>> stats(158) ans =

Area: 43

Centroid: [383.5349 291.4651 229.5116]

BoundingBox: [380.5000 287.5000 227.5000 7 8 3]

Image: [8x7x3 logical]

PixelList: [43x3 double]

RadiusC: 5.5227 Sphericity: 0.0609

(23)

noduli.m

noduli.m: carica “noduli_per_master.mat” e calcola delle statistiche sui dati, allenando poi un classificatore lineare o una rete neurale artificiale

>> noduli

>> confronto = [labtest y]

confronto = 0 0 0 0

<omissis>

1 0 1 1 1 1 1 1 1 1 TP = 12 FN = 2 FP = 31 TN = 1087

sensitivity = 0.8571 specificity = 0.9723

Il file di dati contiene le feature calcolate su un gran numero di noduli e non-noduli (rispettivamente 27 e 2236) provenienti da alcune TC polmonari.

Le feature sono:

volume - raggio mm - sfericita' e intensita' media (colonne da 1 a 4)

(24)

Distribuzioni e scatter-plot delle features

Riferimenti

Documenti correlati

- È un prisma quadrato con l'altezza congruente ai lati - Tutti gli spigoli di un cubo sono congruenti tra loro.. - Gli angoli solidi interni misurano

Le utilizzazioni forestali eseguite nei boschi cedui di castagno sono quelle meglio classificate con il classificatore k-NN applicato congiunta- mente a tutti i quattro indici T (T

31 - Esercizi di riepilogo e di complemento. Area di una superficie

[r]

Gli interventi sui sistemi di illuminazione interna (degli ambienti di lavoro) ed esterna (di sicurezza e dei giardini), quali per esempio la sostituzione di lampade ed

Già abbiamo incontrato le superficie Già abbiamo incontrato le superficie in in R R 3 3 come grafico di una funzione.. come grafico di

massa miocardica, 60° nei sani -Potenziale medio generato dai ventricoli durante. la depolarizzazione, dato dalla lunghezza

massa miocardica, 60° nei sani -Potenziale medio generato dai ventricoli durante. la depolarizzazione, dato dalla lunghezza