Come configurare smartphone e PC. Portale informativo
  • casa
  • Errori
  • Metodi di segmentazione delle immagini. Visualizza il risultato utilizzando un'immagine a colori

Metodi di segmentazione delle immagini. Visualizza il risultato utilizzando un'immagine a colori

La soglia è probabilmente il metodo di segmentazione più semplice, che ha attirato molta attenzione da parte degli esperti. Il metodo si concentra sull'elaborazione di immagini, le cui singole aree omogenee differiscono per la luminosità media. Il tipo di segmentazione più semplice e allo stesso tempo più utilizzato è la segmentazione binaria, quando esistono solo due tipi di aree omogenee. In questo caso, la trasformazione di ogni punto dell'immagine sorgente in quella di output viene eseguita secondo la regola:

(7.1)

dove è l'unico parametro di elaborazione chiamato soglia. I livelli di luminosità in uscita e possono essere arbitrari; servono solo come marcatori, con l'aiuto dei quali viene contrassegnata la mappa risultante, assegnando i suoi punti alle classi o, rispettivamente. Se la preparazione risultante è predisposta per la percezione visiva, spesso i loro valori corrispondono ai livelli di bianco e nero. Se sono presenti più di due classi, la soglia deve specificare una famiglia di soglie che separano le luminosità delle diverse classi l'una dall'altra.

La questione centrale della segmentazione delle soglie è la determinazione delle soglie, che dovrebbe essere eseguita automaticamente. I metodi attualmente utilizzati per la determinazione automatica della soglia sono descritti in dettaglio nella revisione. La varietà di metodi è molto ampia, ma si basano principalmente sull'analisi dell'istogramma dell'immagine originale.

Sia , l'istogramma dell'immagine digitale originale. Supponiamo che il suo intervallo di luminosità sia compreso tra 0 (livello del nero) e 255 (livello del bianco). L'idea originale del metodo di soglia dell'istogramma si basava sul presupposto che le distribuzioni di probabilità per ciascuna classe siano unimodali (contenenti un picco) e che i punti di confine che separano le aree di diverse classi nell'immagine siano pochi. Questi presupposti devono essere soddisfatti da un istogramma di natura multimodale. Le singole mod corrispondono varie classi, e le depressioni che le separano sono regioni di confine con un piccolo numero di punti inclusi in esse. Le soglie di segmentazione sono determinate dalla posizione delle depressioni. Riso. 7.1 illustra quanto sopra in relazione al caso di due classi. In realtà, è estremamente raro utilizzare considerazioni così semplici per selezionare una soglia. Il fatto è che gli istogrammi reali sono solitamente molto frastagliati, come illustrato dal risultato dell'esperimento mostrato in Fig. 7.2. Questo costituisce il primo ostacolo alla determinazione dei punti minimi. Il secondo ostacolo è che i confini tra le aree omogenee dell'immagine sono sfumati, per cui aumenta il livello dell'istogramma in quelle parti di esso che mostrano punti di confine. Ovviamente questo porta ad una diminuzione dei buchi nell'istogramma o addirittura alla loro scomparsa.

Fig. 7.1. Alla scelta della soglia di segmentazione binaria

Uno dei modi efficaci per superare queste difficoltà è determinare la soglia in base al cosiddetto criterio discriminante. Consideriamo questo approccio in relazione a due classi, dalla generalizzazione al caso Di più le lezioni non sono un problema fondamentale. Riteniamo quindi che la distribuzione sia costruita per un'immagine contenente due tipi di aree, e che esista un confine ottimale che le separa nel migliore dei modi in un certo senso. Per determinare la soglia ottimale costruiamo una funzione discriminante , , il cui argomento ha il significato di soglia di prova. Il suo valore che massimizza la funzione è la soglia ottimale. Consideriamo la costruzione di una funzione discriminante.

Sia un ipotetico valore di soglia che suddivide la distribuzione in due classi. In questo caso, di solito non gioca un ruolo importante a quale delle classi verranno assegnati i punti dell'immagine con luminosità, a causa del piccolo numero di punti di confine che separano le aree di classi diverse. La probabilità che un punto del fotogramma preso casualmente appartenga alla classe è uguale a

(7.2)

Allo stesso modo, la probabilità che appartenga a una classe è determinata dalla formula

(7.3)

Inoltre, a causa della normalizzazione della distribuzione di probabilità, l’uguaglianza vale

Successivamente, assumiamo che l'area di distribuzione , limitata dal punto , descriva la parte dell'immagine appartenente a , e l'area , - appartenente a . Questo ci permette di introdurre due distribuzioni e , corrispondenti a e , costruendole dalla distribuzione utilizzando le espressioni:

Qui, la divisione per probabilità garantisce la normalizzazione delle distribuzioni condizionali introdotte.

È possibile trovare i momenti per le distribuzioni di probabilità formate in questo modo. Espressioni per aspettative matematiche e hanno la forma

(7.4)

Dove - aspettativa matematica non standardizzata per , - aspettativa matematica per l'intero fotogramma.

Allo stesso modo, la varianza giornaliera dell'intero fotogramma è data da

(7.6)

Per costruire una funzione discriminante, introduciamo inoltre un altro parametro energetico, chiamato dispersione interclasse:

La funzione discriminante adimensionale è data da

(7.8)

La soglia ottimale, come menzionato sopra, è considerata conforme al requisito

(7.9)

Spieghiamo il significato del criterio (7.9). Il denominatore nell'espressione (7.8) è la dispersione dell'intero fotogramma e, quindi, non dipende dal valore della soglia di prova che divide l'immagine in classi. Pertanto il punto massimo di espressione (7.8) coincide con il punto massimo del numeratore, cioè è determinata dalla natura della dipendenza della varianza interclasse (7.7) dalla soglia . Poiché tende a zero, anche la probabilità, come segue dalla (7.2), tende a zero. Poiché l'intera immagine appartiene alla classe, c'è una tendenza. Di conseguenza, entrambi i termini in (7.7) diventano uguale a zero. Lo stesso si osserva all'altro valore estremo della soglia = 255. A causa della non negatività delle quantità comprese nelle (7.7) e (7.9) e dell'uguaglianza della funzione a zero ai bordi del dominio di definizione, all'interno di questo dominio esiste un massimo, la cui ascissa è presa come la soglia ottimale. Vale la pena notare la natura qualitativa di queste considerazioni. Studi più approfonditi mostrano, ad esempio, che durante l'elaborazione di alcune immagini, la funzione discriminante ha diversi massimi anche se nell'immagine ci sono solo due classi. Ciò, in particolare, si manifesta quando le superfici totali dei lotti occupati dalle classi e sono significativamente diverse. Quindi il compito è caso generale alquanto complicato dalla necessità di determinare il massimo assoluto della funzione.

Da un punto di vista computazionale, per eseguire l'algoritmo, è necessario trovare l'aspettativa matematica e la varianza per l'intera immagine. Successivamente, per ciascun valore, le probabilità vengono determinate utilizzando (7.2) e (7.3) (o condizioni di normalizzazione), nonché le aspettative matematiche delle classi e utilizzando le relazioni (7.4), (7.5). Le quantità così trovate permettono di determinarne il valore.

La quantità di calcoli può essere ridotta eseguendo alcune trasformazioni della formula (7.7) per la varianza interclasse. Utilizzando le formule (7.2)...(7.5), è facile ottenere la relazione per le aspettative matematiche:

(7.11)

Esprimendo la quantità dalla (7.10) e sostituendola nella (7.11), si ottiene infine:

(7.12)

La relazione (7.12), utilizzata come lavoro, include solo due quantità: probabilità e aspettativa matematica non normalizzata, che riduce significativamente la quantità di calcoli quando si trova automaticamente la soglia ottimale.

Nella fig. La Figura 7.2 mostra i risultati sperimentali che illustrano il metodo descritto di segmentazione binaria automatica. La Figura 7.2, a mostra una fotografia aerea della sezione “Campo” della superficie terrestre e la Figura 7.2, b – il risultato della sua segmentazione binaria, eseguita sulla base della determinazione automatica della soglia utilizzando il metodo discriminante. L'istogramma della distribuzione dell'immagine originale è mostrato in Fig. 7.2, c, e la funzione discriminante calcolata dall'istogramma risultante è mostrata in Fig. 7.2, d. Forte irregolarità dell'istogramma, generatrice un gran numero di minimi, esclude la possibilità di determinare direttamente l'unica informazione minima che separa le classi tra loro. La funzione è notevolmente più fluida e, inoltre, in in questo caso unimodale, il che rende la determinazione della soglia un compito molto semplice. La soglia ottimale alla quale si ottiene un'immagine segmentata è =100. I risultati mostrano che il metodo descritto per trovare la soglia, essendo uno sviluppo dell'approccio a istogramma, ha un forte effetto di livellamento in relazione alla ruvidezza dell'istogramma stesso.

Tocchiamo la questione della segmentazione della soglia delle immagini non stazionarie. Se la luminosità media cambia all'interno di un fotogramma, dovrebbero cambiare anche le soglie di segmentazione. Spesso in questi casi si ricorre alla divisione dell'inquadratura in zone separate, all'interno delle quali si possono trascurare variazioni di luminosità media. Ciò consente di applicare i principi di soglia all'interno delle singole aree adatte a lavorare con immagini fisse. In questo caso, l'immagine elaborata mostra le aree in cui è divisa l'immagine originale e i confini tra le aree sono chiaramente visibili. Questo - inconveniente significativo metodo.

Una procedura più laboriosa, ma anche più efficace utilizza una finestra scorrevole, in cui ogni nuova posizione dell'area di lavoro differisce dalla precedente solo di un passo lungo la riga o la colonna. La soglia ottimale trovata ad ogni passo è riferita al punto centrale dell'area corrente. Con questo metodo, quindi, la soglia cambia in ogni punto dell'inquadratura, e tali cambiamenti hanno un carattere paragonabile alla natura della non stazionarietà dell'immagine stessa. La procedura di elaborazione, ovviamente, diventa notevolmente più complicata.

Un compromesso è una procedura in cui, invece di una finestra scorrevole con un singolo passaggio, viene utilizzata una finestra “saltante”, spostando più passaggi in ogni fase della lavorazione. Nei punti “mancati” del fotogramma, la soglia può essere determinata mediante interpolazione (spesso viene utilizzato il metodo più semplice interpolazione lineare) in base ai valori trovati nei punti più vicini.

Fig. 7.2 Esempio di segmentazione binaria con determinazione automatica della soglia

Valutare l’efficacia della segmentazione della soglia in Fig. 7.2, b), si precisa che questo metodo permette di ottenere una certa idea della natura delle aree omogenee che formano il quadro osservato. Allo stesso tempo, è evidente la sua imperfezione fondamentale, causata dalla natura monopunto delle decisioni prese. Pertanto, nelle sezioni seguenti ci rivolgiamo ai metodi statistici che ci consentono di tenerne conto durante la segmentazione proprietà geometriche aree: dimensioni, configurazione, ecc. Notiamo subito che le corrispondenti caratteristiche geometriche sono specificate dai propri modelli probabilistici e molto spesso in forma implicita.

La soglia è uno dei metodi principali per la segmentazione delle immagini grazie alle sue proprietà intuitive. Questo metodo si concentra sull'elaborazione delle immagini, le cui singole aree omogenee differiscono per la luminosità media. Il metodo più comune di segmentazione mediante soglia è la segmentazione binaria, ovvero quando abbiamo a disposizione due tipologie di aree omogenee.

In questo caso, l'immagine viene elaborata pixel per pixel e la conversione di ciascun pixel dell'immagine in ingresso in quella in uscita è determinata dalla relazione:

dove è un parametro di elaborazione chiamato soglia e sono i livelli di luminosità in uscita. L'elaborazione per pixel, la cui posizione nell'immagine non ha alcun ruolo, è chiamata elaborazione punti. I livelli svolgono il ruolo di segni. Determinano a quale tipo appartengono. questo punto: a H0 o a H1. Oppure dicono che H0 è costituito da punti di sfondo e H1 da punti di interesse. Di norma, i livelli corrispondono ai livelli di bianco e nero. Chiameremo le classi H1 (ovvero la classe di interesse) la classe degli oggetti e la classe H0 la classe dello sfondo.

Naturalmente la segmentazione non può essere solo binaria e in questo caso esistono più di due classi esistenti. Questo tipo di segmentazione è chiamata multilivello. L'immagine risultante non è binaria, ma è composta da segmenti di luminosità variabile. Formalmente questa operazione può essere scritto come segue:

dove è il numero di livelli e sono le classi di immagine. In questo caso, per ciascuna delle classi, dovrà essere fissata un'opportuna soglia che separi tali classi tra loro. Le immagini binarie sono più facili da archiviare ed elaborare rispetto alle immagini con molti livelli di luminosità.

La cosa più difficile riguardo alla soglia è il processo di determinazione della soglia stessa. La soglia è spesso scritta in funzione della forma:

dove è l'immagine, ed è una caratteristica del punto dell'immagine, ad esempio, la luminosità media nell'area centrata in questo punto.

Se il valore di soglia dipende solo da, cioè è lo stesso per tutti i punti dell'immagine, tale soglia viene chiamata globale. Se la soglia dipende dalle coordinate spaziali, tale soglia viene chiamata locale. Se dipende dalle caratteristiche, tale soglia viene chiamata adattiva. Pertanto, l'elaborazione è considerata globale se si applica all'intera immagine nel suo insieme e locale se si applica a una determinata area selezionata.

Oltre alle distinzioni elencate tra gli algoritmi, esistono molti altri metodi. Molti di essi sono semplicemente una combinazione di altri, ma la maggior parte di essi, in un modo o nell'altro, si basa sull'analisi dell'istogramma dell'immagine originale, tuttavia esistono fondamentalmente altri approcci che non influenzano l'analisi degli istogrammi in forma diretta oppure passare da essi all'analisi di alcune altre funzioni.

Segmentazione delle immagini con U-Net in pratica

introduzione

In questo post del blog esamineremo come funziona Unet, come implementarlo e quali dati sono necessari per addestrarlo. Per fare questo considereremo:

  1. come fonte di ispirazione.
  2. Pitorciacome strumento per realizzare la nostra idea.
  3. Gare di Kaggle come luogo in cui possiamo testare le nostre ipotesi su dati reali.

Non seguiremo l'articolo al 100%, ma cercheremo di coglierne l'essenza e adattarlo alle nostre esigenze.

Presentazione del problema

In questo problema ci viene data l'immagine di un'auto e la sua maschera binaria (localizzazione della posizione dell'auto nell'immagine). Vogliamo creare un modello in grado di separare l'immagine dell'auto dallo sfondo con una precisione pixel per pixel superiore al 99%.

Per capire cosa vogliamo, l'immagine gif è qui sotto:

L'immagine a sinistra è l'immagine originale, a destra c'è la maschera che verrà applicata all'immagine. Utilizzeremo una rete neurale Unet che imparerà a creare automaticamente una maschera.

  1. Inserimento di immagini di automobili nella rete neurale.
  2. Utilizzando una funzione di perdita, confrontando l'output della rete neurale con le maschere corrispondenti e restituendo un errore alla rete per scoprire dove la rete non funziona.

Struttura del codice

Il codice è stato semplificato il più possibile per capirne il funzionamento. Il codice principale è in questo file main.py , esaminiamolo riga per riga.

Codice

Itereremo il codice in main.py e l'articolo. Non preoccuparti dei dettagli nascosti in altri file di progetto: ti mostreremo quelli che ti servono secondo necessità.

Cominciamo dall'inizio:

def main(): #Iperparametri input_img_resize = (572, 572) # La dimensione di ridimensionamento delle immagini di input della rete neurale output_img_resize = (388, 388) # La dimensione di ridimensionamento delle immagini di output della rete neurale dimensione_batch = 3 epoche = 50 soglia = 0.5 dimensione_validazione = 0.2 dimensione_campione = Nessuna # -- Parametri opzionali threads = cpu_count() use_cuda = torch.cuda.is_available() script_dir = os.path.dirname(os.path. abspath(__file__ )) # Callback di addestramento tb_viz_cb = TensorboardVisualizerCallback(os.path.join(script_dir,"../logs/tb_viz" )) tb_logs_cb = TensorboardLoggerCallback(os.path.join(script_dir,"../logs/tb_logs" )) model_saver_cb = ModelSaverCallback(os.path.join(script_dir,"../output/models/model_" + helpers.get_model_timestamp()), verbose= True )

Nella prima sezione definisci i tuoi iperparametri, che puoi configurare in base alle tue esigenze, ad esempio in base alla memoria della tua GPU. Parametri ottimali definirne alcuni parametri utili E richiamate. TensorboardVisualizerCallback è una classe in cui memorizzerà le previsioni tensore in ogni fase del processo formativo, TensorboardLoggerCallback conserverà i valori della funzione di perdita e la “precisione” pixel per pixel tensore. E infine ModelSaverCallback salverà il modello al termine dell'addestramento.

# Scarica i set di dati ds_fetcher = DatasetFetcher () ds_fetcher. download_dataset()

Questa sezione scarica e recupera automaticamente un set di dati da Kaggle. Si prega di notare che per lavoro di successo questo pezzo di codice devi avere account Kaggle con nome utente e password, che dovrebbero essere inseriti nelle variabili di ambiente KAGGLE_USER E KAGGLE_PASSWD prima di eseguire lo script. È inoltre necessario accettare le regole del concorso prima di caricare i dati. Questo può essere fatto sulla schedascaricare i dati della competizione

# Ottieni il percorso dei file per la rete neurale X_train, y_train, X_valid, y_valid = ds_fetcher.get_train_files(sample_size= sample_size, validation_size= validation_size) full_x_test = ds_fetcher.get_test_files(sample_size) # Test dei callback pred_saver_cb = PredictionsSaverCallback(os.path. join (script_dir, "../output/submit.csv.gz" ), origin_img_size, soglia)

Questa linea definisce richiamare funzione per test (o previsione). Salverà le previsioni in un file gzip ogni volta che viene effettuata una nuova serie di previsioni. Pertanto, le previsioni non verranno archiviate in memoria, poiché sono di dimensioni molto grandi.

Una volta completato il processo di previsione, puoi inviare il file risultante send.csv.gz dalla cartella di output in Kaggle.

# -- Definire la nostra architettura di rete neurale# Il documento originale ha 1 canale di ingresso, nel nostro caso ne abbiamo 3 (RGB) net = unet_origin. UNetOriginal ((3 , *img_resize)) classificatore = nn. classificatore. CarvanaClassifier (netto, epoche) ottimizzatore = optim. SGD (net. parametri() , lr= 0.01 , momentum= 0.99 ) train_ds = TrainImageDataset (X_train , y_train, input_img_resize, output_img_resize, X_transform = aug. augment_img) train_loader = DataLoader (train_ds, batch_size, sampler= RandomSampler (train_ds), num_workers = thread, pin_memory= use_cuda) valid_ds = TrainImageDataset (X_valid, y_valid, input_img_resize, output_img_resize, soglia= soglia) valid_loader = DataLoader (valid_ds, batch_size, sampler= SequentialSampler (valid_ds), num_workers= thread, pin_memory= use_cuda)

stampa( "Formazione su () campioni e convalida su () campioni". format(len(train_loader. dataset), len(valid_loader. dataset))) # Addestra il classificatore classificatore. train(train_loader, valid_loader, epoche, callbacks= )

test_ds = TestImageDataset (full_x_test, img_resize) test_loader = DataLoader (test_ds, batch_size, sampler= SequentialSampler (test_ds), num_workers= threads, pin_memory= use_cuda) # Prevedi e salva classificatore. predit(test_loader, callbacks= ) pred_saver_cb. chiudi_salva()

Infine, facciamo lo stesso di sopra, ma per eseguire la previsione. Chiamiamo il nostro pred_saver_cb.close_saver() per cancellare e chiudere il file che contiene le previsioni.

Implementazione di un'architettura di rete neurale

Articolo Unet presenta un approccio per la segmentazione delle immagini mediche. Tuttavia, risulta che questo approccio può essere utilizzato anche per altri problemi di segmentazione. Incluso quello su cui lavoreremo ora.

Dovresti leggere l'intero articolo almeno una volta prima di andare avanti. Non preoccuparti se non ricevi piena comprensione apparato matematico, potete saltare questa sezione, così come il capitolo “Esperimenti”. Il nostro obiettivo è ottenere il quadro generale.

Lo scopo dell'articolo originale è diverso dal nostro, dovremo adattare alcune parti in base alle nostre esigenze.

Al momento della stesura del lavoro mancavano 2 cose che ora sono necessarie per accelerare la convergenza di una rete neurale:

  1. Norma batch.
  2. GPU potenti.

Il primo è stato inventato appena 3 mesi prima Unet, e probabilmente è troppo presto per gli autori Unet lo ha aggiunto al nostro articolo.

Ad oggi Norma batch usato quasi ovunque. Puoi eliminarlo nel codice se vuoi valutare l'articolo al 100%, ma potresti non vivere abbastanza per vedere la convergenza della rete.

Per quanto riguarda le GPU, l'articolo afferma:

Per ridurre al minimo il sovraccarico e sfruttare al massimo la memoria della GPU, preferiamo riquadri di input di grandi dimensioni rispetto a batch di grandi dimensioni e quindi riduciamo il batch a una singola immagine

Hanno usato una GPU con 6 GB di RAM, ma attualmente la GPU più memoria, per posizionare le immagini in un batch. Il lotto attuale è pari a tre, funziona per GPU nella GPU con 8 GB di RAM. Se non disponi di una scheda video di questo tipo, prova a ridurre il batch a 2 o 1.

Per quanto riguarda i metodi aumenti (cioè distorsioni dell'immagine originale secondo uno schema) discusse nell'articolo, ne utilizzeremo di diverse da quelle descritte nell'articolo, poiché le nostre immagini sono molto diverse dalle immagini biomediche.

Ora cominciamo dall'inizio progettando l'architettura della rete neurale:

Questo è l'aspetto di Unet. Puoi trovare un'implementazione equivalente Pytorch nel modulo nn.unet_origin.py.

Tutte le classi in questo file hanno almeno 2 metodi:

  • __dentro__()dove inizializzeremo i nostri strati di rete neurale;
  • inoltrare()che è un metodo chiamato quando rete neurale riceve l'ingresso.

Vediamo i dettagli di implementazione:

  • ConvBnRelu è un blocco contenente le operazioni Conv2D, BatchNorm e Relu. Invece di digitarne 3 per ogni stack di codificatore (gruppo di operazioni giù) e stack di decodificatori (gruppo di operazioni su), li raggruppiamo in questo oggetto e lo riutilizziamo secondo necessità.
  • StackEncoder incapsula l'intero "stack" di operazioni, comprese le operazioni ConvBnRelu E MaxPool come sotto:



Monitoriamo il ritiro ultima operazione ConvBnRelu V x_traccia e restituirlo perché concateneremo questo output utilizzando gli stack del decodificatore.

  • StackDecoderè uguale a StackEncoder, ma per le operazioni di decodifica, circondato di seguito in rosso:



Da notare che tiene conto dell'operazione di trim/concatenazione (circondata in arancione) passando down_tensor, che non è altro che il tensore x_trace restituito dal nostro StackEncoder .

  • UNetOriginal- Qui è dove avviene la magia. Questa è la nostra rete neurale che assemblerà tutti i mattoncini presentati sopra. Metodi dentro E inoltrare sono davvero complessi, aggiungono un sacco di cose StackEncoder , la parte centrale e alla fine diversi StackDecoder . Quindi otteniamo l'output StackDecoder , aggiungiamo una convoluzione 1x1 come da articolo, ma invece di definire due filtri come output, ne definiamo solo 1, che sarà effettivamente la nostra previsione della maschera in scala di grigi. Successivamente, "comprimiamo" il nostro output per rimuovere la dimensione del canale (è solo 1, quindi non è necessario memorizzarlo).

Se vuoi capire più dettagli di ciascun blocco, metti punto di controllo eseguire il debug nel metodo forward di ciascuna classe per visualizzare gli oggetti in dettaglio. Puoi anche stampare la forma dei tuoi tensori di output tra i livelli eseguendo print ( x.dimensione() ).

Formazione sulla rete neurale

  1. Funzione di perdita

Ora passiamo al mondo reale. Secondo l'articolo:

La funzione energetica viene calcolata da un soft-max in termini di pixel sulla mappa delle caratteristiche finale combinata con il funzione di perdita di entropia incrociata.

Il fatto è che nel nostro caso vogliamo usare coefficiente dei dadi come funzione di perdita invece di quella che chiamano "funzione energetica" poiché questa è la metrica utilizzataConcorso Kaggle , che è definito:

Xè la nostra previsione e Y- una maschera correttamente contrassegnata sull'oggetto corrente. |X| significa la potenza del set X(il numero di elementi in questo insieme) e ∩ per l'intersezione tra X E Y.

Il codice per il coefficiente dei dadi può essere trovato in nn.losses.SoftDiceLoss .

class SoftDiceLoss (nn.Module): def __init__(self, peso= None, size_average= True): super (SoftDiceLoss, self).__init__() def forward(self, logits, target): smooth = 1 num = target.size (0 ) probs = F.sigmoid(logits) m1 = probs.view(num, - 1 ) m2 = target.view(num, - 1 ) intersezione = (m1 * m2) punteggio = 2 . * (intersection.sum(1 ) + smooth) / (m1.sum(1 ) + m2.sum(1 ) + smooth) punteggio = 1 - score.sum() / num return punteggio

Il motivo per cui l'intersezione è implementata come moltiplicazione e la potenza come somma() Di asse 1 (somma di tre canali) è che i pronostici e l'obiettivo sono codificato a caldo vettori.

Ad esempio, supponiamo che la previsione sul pixel (0, 0) sia 0,567 e che l'obiettivo sia 1, otteniamo 0,567 * 1 = 0,567. Se il target è 0, otteniamo 0 in quella posizione del pixel.

Abbiamo anche utilizzato un fattore uniforme pari a 1 per la backpropagation. Se la previsione è una soglia fissa pari a 0 e 1, è difficile effettuare la retropropagazione perdita di dadi.

Confronteremo quindi la perdita dei dadi con l'entropia incrociata per ottenere la nostra funzione di perdita totale, che puoi trovare nel metodo _criterio da nn.Classifier.CarvanaClassifier . Secondo l'articolo originale, usano anche una mappa del peso nella funzione di perdita di entropia incrociata per dare ad alcuni pixel un errore in più durante l'addestramento. Nel nostro caso, non abbiamo bisogno di una cosa del genere, quindi usiamo semplicemente l'entropia incrociata senza alcuna mappa del peso.

2. Ottimizzatore

Poiché non abbiamo a che fare con immagini biomediche, utilizzeremo le nostre aumenti . Il codice può essere trovato in img.augmentation.augment_img. Lì eseguiamo la traslazione, la rotazione, il capovolgimento e il ridimensionamento casuali.

Formazione sulla rete neurale

Ora puoi iniziare ad allenarti. Con il progredire di ogni epoca, sarai in grado di visualizzare le previsioni del tuo modello sul set di validazione.

Per fare questo devi correre Tensorboard nella cartella logs utilizzando il comando:

Tensorboard --logdir=./logs

Un esempio di ciò che puoi vedere in Tensorboard dopo l'epoca 1:

Segmentazione guidata dei bacini idrografici

Molto spesso, quando si analizzano le immagini, si presenta il compito di dividere i pixel dell'immagine in gruppi in base a determinate caratteristiche. Questo processo di divisione in gruppi è chiamato segmentazione. I più noti sono due tipi di segmentazione: la segmentazione in base alla luminosità per le immagini binarie e la segmentazione in base alle coordinate di colore per le immagini a colori. I metodi di segmentazione possono essere considerati come una formalizzazione del concetto di distinzione di un oggetto dallo sfondo o di concetti associati a un gradiente di luminosità. Gli algoritmi di segmentazione sono caratterizzati da determinati parametri di affidabilità e accuratezza dell'elaborazione. Dipendono da quanto pienamente vengono presi in considerazione caratteristiche aggiuntive distribuzione della luminosità nelle aree degli oggetti o dello sfondo, numero di variazioni di luminosità, forma degli oggetti, ecc.

Esistono molte immagini che contengono l'oggetto di interesse con una luminosità abbastanza uniforme su uno sfondo di luminosità diversa. Gli esempi includono testo scritto a mano, una serie di immagini mediche, ecc. Se la luminosità dei punti dell'oggetto differisce nettamente dalla luminosità dei punti dello sfondo, risolvere il problema della definizione di una soglia è un compito semplice. In pratica, questo non è così semplice, poiché l'immagine in esame è soggetta a rumore ed è consentita qualche variazione nei valori di luminosità. Esistono diversi approcci analitici al limite della soglia di luminosità. Un metodo consiste nell'impostare la soglia a un livello al quale importo totale gli elementi con luminosità sottosoglia sono coerenti con le probabilità a priori di questi valori di luminosità.

Approcci simili possono essere applicati all'elaborazione di immagini a colori e spettrozonali. Esiste anche un tipo di segmentazione chiamata segmentazione del contorno. Molto spesso, l'analisi delle immagini include operazioni come l'ottenimento del contorno esterno delle immagini degli oggetti e la registrazione delle coordinate dei punti su questo contorno. Esistono tre approcci principali per rappresentare i confini di un oggetto: approssimazione della curva, tracciamento del contorno e collegamento dei punti di rilascio. Per completare l'analisi è opportuno notare che è presente anche la segmentazione delle texture e la segmentazione delle forme.

Maggior parte vista semplice la segmentazione è la segmentazione della soglia. Ha trovato ampia applicazione nella robotica. Ciò è spiegato dal fatto che in quest'area le immagini degli oggetti studiati hanno per la maggior parte una struttura abbastanza uniforme e il loro sfondo risalta nettamente. Ma oltre a questo, per un'elaborazione affidabile è necessario sapere che l'immagine è composta da un oggetto e uno sfondo, la cui luminosità rientra in intervalli strettamente noti e non si intersecano tra loro.

Lo sviluppo delle tecnologie di elaborazione delle immagini ha portato all'emergere di nuovi approcci alla risoluzione dei problemi di segmentazione delle immagini e alla loro applicazione nella risoluzione di molti problemi pratici.

In questo lavoro considereremo relativamente nuovo approccio alla soluzione del problema della segmentazione delle immagini: il metodo dello spartiacque. Spieghiamo brevemente il nome di questo metodo e qual è la sua essenza.

Si propone di considerare l'immagine come una mappa del territorio, dove i valori di luminosità rappresentano valori di altezza relativi ad un certo livello. Se quest'area è piena d'acqua, si formano delle pozze. Quando vengono ulteriormente riempite d'acqua, queste piscine vengono combinate. I punti in cui questi bacini si uniscono sono contrassegnati come linee spartiacque.

La separazione degli oggetti che si toccano in un'immagine è uno dei problemi importanti dell'elaborazione delle immagini. Spesso per risolvere questo problema viene utilizzato il cosiddetto metodo spartiacque marcatore. Le trasformazioni che utilizzano questo metodo devono identificare "bacini idrografici" e "linee di divisione" in un'immagine elaborando le aree locali in base alle loro caratteristiche di luminosità.

Il metodo Marker Watershed è uno dei più utilizzati metodi efficaci segmentazione delle immagini. Quando si implementa questo metodo, vengono eseguite le seguenti procedure di base:

    Viene calcolata la funzione di segmentazione. Si tratta di immagini in cui gli oggetti si trovano in zone scure e sono difficili da vedere.

    Calcolo dei gettoni primo piano immagini. Vengono calcolati sulla base di un'analisi della connettività dei pixel di ciascun oggetto.

    Calcolo dei marcatori di sfondo. Rappresentano pixel che non fanno parte di oggetti.

    Modifica della funzione di segmentazione in base ai valori di posizione dei marcatori di sfondo e dei marcatori di primo piano.

    Calcoli basati su una funzione di segmentazione modificata.

IN in questo esempio tra le funzioni del pacchetto Elaborazione delle immagini Le funzioni più comunemente utilizzate di Toolbox sono fspecial, imfilter, watershed, label2rgb, imopen, imclose, imreconstruct, imcomplement, imregionalmax, bwareaopen, greythresh e imimposemin.

  • Passaggio 1: leggi un'immagine a colori e convertila in scala di grigi.
  • Passaggio 2: utilizzo del valore del gradiente come funzione di segmentazione.
  • Passaggio 3: etichettare gli oggetti in primo piano.
  • Passaggio 4: calcolare i marcatori di sfondo.
  • Passo 6: Visualizzazione del risultato della lavorazione.

Passaggio 1: leggi un'immagine a colori e convertila in scala di grigi.

Leggiamo i dati dal file Pears.png rgb=imread("pears.png"); e presentarli come un'immagine a mezzitoni. I=rgb2grigio(rgb); imshow(I) text(732,501,"…",... "FontSize",7,"HorizontalAlignment","right")

Passaggio 2: utilizzo del valore del gradiente come funzione di segmentazione.

Per calcolare il valore del gradiente vengono utilizzati l'operatore Sobel, la funzione imfilter e altri calcoli. Il gradiente ha grandi valori sui confini degli oggetti e piccoli (nella maggior parte dei casi) al di fuori dei confini degli oggetti.

Hy=fspecial("sobel"); hx=hy"; Iy=imfilter(double(I), hy, "replica"); Ix=imfilter(double(I), hx, "replica"); gradmag=sqrt(Ix.^2+Iy.^2 ); figura, imshow(gradmag,), titolo("valore gradiente")

Pertanto, dopo aver calcolato i valori del gradiente, è possibile iniziare a segmentare le immagini utilizzando il metodo del marcatore spartiacque considerato.

L=spartiacque(gradmag); Lrgb=etichetta2rgb(L); figura, imshow(Lrgb), titolo("Lrgb")

Tuttavia, senza ulteriori calcoli aggiuntivi, tale segmentazione risulterà superficiale.

Passaggio 3: etichettare gli oggetti in primo piano.

Può essere utilizzato per contrassegnare gli oggetti in primo piano varie procedure. In questo esempio verranno utilizzate tecnologie morfologiche denominate "apertura tramite restauro" e "chiusura tramite restauro". Queste operazioni consentono di analizzare la regione interna degli oggetti immagine utilizzando la funzione imregionalmax.

Come accennato in precedenza, quando si contrassegnano oggetti in primo piano, vengono utilizzate anche operazioni morfologiche. Diamo un'occhiata ad alcuni di essi e confrontiamoli. Per prima cosa implementiamo l'operazione di espansione utilizzando la funzione imopen.

Se=strel("disco", 20); Io=imopen(I, se); figura, imshow(Io), titolo("Io")

Ie=imerode(I, se); Iobr=imricostruisci(Ie, I); figura, imshow(Iobr), titolo("Iobr")

Le successive operazioni di apertura e chiusura morfologica comporteranno lo spostamento delle macchie scure e la formazione di marcatori. Analizziamo le operazioni di chiusura morfologica. Per fare ciò, usa prima la funzione imclose:

Ioc=imclose(Io, se); figura, imshow(Ioc), titolo("Ioc")

Iobrd=imdilata(Iobr, se); Iobrcbr=imricostruisci(implementa(Iobrd), implementa(Iobr)); Iobrcbr=implementa(Iobrcbr); figura, imshow(Iobrcbr), titolo("Iobrcbr")

Comparativo analisi visiva Iobrcbr e Ioc mostrano che la ricostruzione presentata basata su operazioni di apertura e chiusura morfologica è più efficace rispetto a operazioni standard apertura e chiusura. Calcoliamo i massimi locali di Iobrcbr e otteniamo i marcatori in primo piano.

Fgm=imregionalmax(Iobrcbr); figura, imshow(fgm), titolo("fgm")

Applichiamo i marcatori di primo piano all'immagine originale.

I2=Io; I2(fgm)=255; figura, imshow(I2), titolo("fgm sovrapposto all'immagine originale")

Tieni presente che alcuni oggetti nascosti o chiusi nell'immagine non sono etichettati. Questa proprietà influisce sulla formazione del risultato e molti di questi oggetti immagine non verranno elaborati dal punto di vista della segmentazione. Pertanto, gli indicatori di primo piano mostrano solo i confini della maggior parte degli oggetti. I confini così rappresentati sono soggetti ad ulteriore elaborazione. In particolare si tratta di operazioni morfologiche.

Se2=strel(uno(5, 5)); fgm2=imclose(fgm, se2); fgm3=imerode(fgm2, se2);

Come risultato di questa operazione, i singoli pixel isolati dell'immagine scompaiono. Puoi anche utilizzare la funzione bareaopen, che ti consente di rimuovere un numero specificato di pixel.

Fgm4=bwareaaperta(fgm3, 20); I3=Io; I3(fgm4)=255; figura, imshow(I3) titolo("fgm4 sovrapposto all'immagine originale")

Passaggio 4: calcolare i marcatori di sfondo.

Eseguiamo ora l'operazione di marcatura dello sfondo. Nell'immagine Iobrcbr i pixel scuri appartengono allo sfondo. Pertanto, è possibile applicare l'operazione di soglia dell'immagine.

Bw=im2bw(Iobrcbr, greythresh(Iobrcbr)); figura, imshow(bw), titolo("bw")

I pixel dello sfondo sono scuri, ma non possiamo semplicemente eseguire operazioni morfologiche sui marcatori dello sfondo e ottenere i confini degli oggetti che stiamo segmentando. Vogliamo "sfoltire" lo sfondo in modo tale da ottenere un vero scheletro dell'immagine, ovvero il cosiddetto primo piano dell'immagine a mezzitoni. Questo viene calcolato utilizzando un approccio spartiacque e sulla base delle misurazioni della distanza (rispetto alle linee spartiacque).

D=bwdist(bw); DL=spartiacque(D); bgm=DL==0; figura, imshow(bgm), titolo("bgm")

Passo 5: Calcolo del bacino idrografico del marcatore in base alla funzione di segmentazione modificata.

La funzione imimposemin può essere utilizzata per determinare con precisione i minimi locali in un'immagine. Sulla base di ciò, la funzione imimposemin può anche regolare i valori dei gradienti nell'immagine e quindi perfezionare la posizione dei marcatori di primo piano e di sfondo.

Gradmag2=imimposemin(gradmag, bgm | fgm4);

Infine, viene eseguita un'operazione di segmentazione basata sui bacini idrografici.

L=spartiacque(gradmag2);

Passo 6: Visualizzazione del risultato della lavorazione.

Visualizziamo gli indicatori di primo piano sovrapposti, gli indicatori di sfondo e i confini degli oggetti segmentati sull'immagine originale.

I4=Io; I4(imdilata(L==0, unità(3, 3))|bgm|fgm4)=255; figura, imshow(I4) titolo("Marcatori e confini dell'oggetto sovrapposti all'immagine originale")

Come risultato di questa visualizzazione, è possibile analizzare visivamente la posizione degli indicatori di primo piano e di sfondo.

È interessante anche visualizzare i risultati dell'elaborazione utilizzando un'immagine a colori. La matrice generata dalle funzioni watershed e bwlabel può essere convertita in un'immagine truecolor utilizzando la funzione label2rgb.

Lrgb=etichetta2rgb(L, "jet", "w", "shuffle"); figura, imshow(Lrgb) titolo("Lrgb")

È inoltre possibile utilizzare la modalità semitrasparente per sovrapporre una matrice di segni pseudo-colore sull'immagine originale.

Figura, imshow(I), tieni premuto himage=imshow(Lrgb); set(immagine, "AlphaData", 0.3); title("Lrgb sovrapposto all'immagine originale in modalità semitrasparente")

L'articolo descrive uno studio sui metodi di segmentazione delle immagini su vari esempi. Lo scopo dello studio è scoprire i vantaggi e gli svantaggi di alcuni metodi conosciuti.


Metodi che verranno discussi in questo articolo:

  1. Metodo di coltivazione regionale;
  2. Metodo spartiacque;
  3. Metodo dei tagli normali.

Studio di metodi di segmentazione su immagini modello

La ricerca sui metodi di segmentazione è stata inizialmente condotta su modelli di immagini. Nove tipi di immagini sono state utilizzate come modelli.




I risultati dello studio hanno mostrato:

  • Il metodo di crescita della regione localizza i difetti della trama, sia quelli che sono nettamente diversi dallo sfondo, sia quelli formati ruotando e modificando la luminosità della trama;
  • Il metodo di crescita della regione localizza i difetti a vari livelli a diversi angoli di rotazione della trama;
  • Il metodo di segmentazione dello spartiacque considerato in forma originale non fornisce la localizzazione dei difetti di trama;
  • Il metodo dei tagli normali è efficace nel localizzare la presenza di una texture diversa dallo sfondo, ma non evidenzia i cambiamenti di luminosità e rotazione della texture.

Studio di metodi di segmentazione su immagini di oggetti

Per studiare i metodi di segmentazione è stato preparato un database di immagini di vari oggetti. Le immagini risultanti sono state segmentate utilizzando vari metodi, il cui risultato è presentato nelle cifre della tabella


Immagine originale Metodo di coltivazione regionale Metodo dei tagli normali Metodo spartiacque

Risultati:

  • Il metodo di crescita della regione non fornisce la localizzazione dei segmenti nelle immagini degli oggetti;
  • I metodi considerati di spartiacque e sezioni normali nella loro forma originale non forniscono la localizzazione degli oggetti presentati;
  • Il metodo dei tagli normali fornisce la localizzazione degli oggetti nelle immagini degli oggetti.

risultati

Risultati dello studio:

  • Il metodo di crescita della regione non fornisce la localizzazione dei segmenti come in immagini del modello e sulle immagini dell'oggetto e fornisce anche la localizzazione di elementi dell'infrastruttura del trasporto stradale.
  • I metodi considerati di spartiacque e sezioni normali nella loro forma originale non garantiscono completamente la localizzazione degli oggetti presentati.
  • Il metodo dei tagli normali fornisce la localizzazione degli oggetti sia nelle immagini del modello che nelle immagini degli oggetti, e fornisce anche la localizzazione degli elementi dell'infrastruttura del trasporto stradale.
  • Il metodo di crescita regionale e il metodo della sezione normale possono essere consigliati per l'uso in sistemi automatizzati controllo visivo.

I migliori articoli sull'argomento