• Non ci sono risultati.

Algoritmo per l’elaborazione e il conteggio

Il primo passo svolto, al fine di sviluppare un sistema di lettura che come già detto emulasse il più possibile quello manuale, è stato quello di scrivere una funzione che riuscisse ad eseguire un conteggio delle bolle presenti nelle fiale, a partire da una singola immagine. Una volta scelto Matlab quale software preposto alla rielaborazione, la fase successiva è consistita nello sviluppo di un algoritmo. Le operazioni da compiere sono le seguenti:

 Data un’immagine, si restringa l’analisi al solo rivelatore, selezionando un’area rettangolare non troppo grande che lo contenga;

 Si applichi un filtro, che possa eliminare o, dove ciò non fosse possibile, limitare il più possibile il rumore;

 Si trovino le regioni con discontinuità dei livelli di grigio, ovvero con alti valori di derivata spaziale;

 Si osservino gli andamenti di tali regioni, cercando di assegnare un valore nullo a tutti i pixel che non rappresentino un massimo;

Si compia un’operazione di sogliatura, volta a sfoltire ulteriormente il numero dei massimi, eliminando quelli non appartenenti ai contorni degli oggetti di interesse;

 Si effettui il conteggio delle bolle.

Un algoritmo che compia le operazioni desiderate, eccetto il conteggio, è il

42

metodologia impiegata per l’analisi dei contorni, sia ad una dimensione, sia in più dimensioni. Egli, attraverso il calcolo delle variazioni, una tecnica molto usata in matematica per l’analisi e la ricerca dei massimi e dei minimi, ottenne che il funzionale che meglio si adattava ai suoi scopi era la derivata prima di una funzione gaussiana. All’immagine viene prima applicato un filtro Gaussiano che si convolve con l’immagine e che ha lo scopo di eliminare il rumore presente. L’espressione per un generico filtro Gaussiano di ordine (2n+1) è la seguente:

𝐻𝑖𝑗 =2𝜋𝜎12𝑒𝑥𝑝 (−(𝑖−(𝑛+1))22𝜎+(𝑗−(𝑛+1))2 2) ; 1≤ i,j ≤ (2n+1) (14)

dove σ è la deviazione standard del filtro. Ovviamente si può osservare che per piccoli valori di σ si ha uno smoothing lieve ed un taglio limitato delle alte frequenze, mentre per σ elevati l’attenuazione del rumore è notevolmente accentuata rispetto al caso precedente. Tuttavia vengono attenuati anche gli oggetti presenti nell’immagine e dunque, in base all’analisi che si vuole compiere, sarà necessario scegliere un valore adatto, che rappresenti un compromesso tra i due casi precedentemente visti.

La seconda operazione che si esegue sull’immagine e che rappresenta il cuore dell’intero procedimento, è la ricerca del gradiente della luminosità, ovvero lo studio della variazione di intensità luminosa all’interno di una scena. L’algoritmo di Canny compie questa operazione attraverso filtri preposti alla rivelazione degli edge orizzontali verticali e diagonali, sfruttando l’operatore di Sobel. Tale operatore sfrutta la potenza del vettore gradiente, il quale punta nella direzione del maggiore aumento di luminosità, e il cui modulo corrisponde alla rapidità con cui varia l’intensità luminosa.

La fase successiva consiste nell’eliminazione di quei pixel che non appartengono al contorno dell’oggetto che stiamo analizzando all’interno dell’immagine e ai quali verrà assegnato un valore nullo, durante le fasi successive dell’elaborazione. E’ importante notare che un valore elevato di

43

intensità luminosa non identifica necessariamente un punto di edge. Condizione necessaria e sufficiente affinché un pixel appartenga al contorno è che esso rappresenti un massimo locale. Per rimuovere dunque i punti di non interesse, l’algoritmo di Canny ricorre alla sogliatura con isteresi. Tale operazione, consiste nella scelta di due soglie S1 ed S2, con S1>S2. Qualora il valore di un pixel sia superiore ad S1 oppure sia compreso tra S1 ed S2 e non sia in posizione adiacente ad un altro con valore minore di S2, tale punto

potrà dirsi appartenente all’edge. In caso contrario gli sarà assegnato il valore zero, come detto in precedenza.

I risultati ottenuti con questo procedimento sono fortemente influenzati dalle due operazioni fondamentali di filtraggio e sogliatura, infatti la larghezza del filtro Gaussiano regola il rumore, mentre la seconda determina le informazioni che saranno perse e quelle che invece andranno a costituire i risultati dell’elaborazione. Naturalmente tali parametri andranno regolati in base alle esigenze, all’oggetto dell’analisi e ad altri fattori come ad esempio la pesantezza in termini di potenza di calcolo. Si può affermare inoltre che la genericità di questo algoritmo, da un lato fornisce una vasta possibilità di impiego, dall’altro permette l’aggiunta di comandi e funzioni specifiche, volte al miglioramento delle prestazioni in una precisa configurazione. Nel caso analizzato in questo particolare lavoro di tesi, è stato scritto il codice di una funzione che potesse lavorare nel modo fino ad ora discusso, e che fosse in grado di fornire misure sufficientemente precise. In principio si hanno i seguenti comandi:

function BWfinal=canny(nome)

I = imread(nome);

I = I (165:375,50:630,1);

Queste prime righe sono utili a delineare l’identità della funzione. L’ultimo comando di questa porzione dell’algoritmo ha lo scopo di restringere

44

l’analisi alla sola raffigurazione del rivelatore. Quest’operazione ha il compito di impedire che vengano trovati oggetti al di fuori della fiala, diminuendo così l’errore sul conteggio che verrà eseguito al termine dell’elaborazione. I numeri riportati non sono fissi, ma variano in base all’immagine, alla sua risoluzione e all’area che si vorrà indagare. Le cifre in questione sono riferite in particolare al caso mostrato in figura 27. Il risultato della selezione è visibile invece in figura 28.

Figura 27. Immagine di partenza, [23].

45

La fase successiva vede come protagonista l’operatore di Sobel definito in precedenza.

threshold = edge(I, 'sobel'); fudgeFactor = .5;

BWs = edge( threshold * fudgeFactor,'sobel');

Esso viene applicato due volte. Nella seconda in particolare si ha l’introduzione di un fudge factor ossia un parametro il cui valore ottimizza i risultati, contrastando gli eventuali errori di tale operatore.

Figura 29. Seconda fase dell’elaborazione: applicazione dell'operatore di Sobel.

A questo punto, l’elaborazione prevede un’ulteriore modifica. Dobbiamo infatti eliminare il bordo della fiala, evidenziare gli oggetti che corrispondono effettivamente a delle bolle ed eliminare gli altri, in modo da facilitare il conteggio che avverrà in seguito.

se90 = strel('line', 3, 90); se0 = strel('line', 3, 0);

BWsdil = imdilate(BWs, [se90 se0]); Bwdfill = imfill(BWsdil, 'holes');

BWnobord = imclearborder(BWdfill, 4); seD = strel('diamond',1);

46

BWfinal = imerode(BWnobord,seD); BWfinal = imerode(BWfinal,seD); BWfinal = bwareaopen(BWfinal,10);

Le prime due righe di questa porzione di codice hanno lo scopo di evidenziare gli oggetti rilevati fino ad ora. La funzione strel dilata i contorni servendosi di un elemento strutturale, in questo caso una linea, con lunghezza ed angolo specificati tra i parametri. La sua dimensione viene espressa in pixel, mentre l’ampiezza angolare è scritta in gradi rispetto all’orizzontale, prendendo come positivo il senso orario. L’operazione successiva alla dilatazione è il riempimento dei buchi all’interno delle strutture rilevate. Subito dopo viene eseguita l’eliminazione delle strutture connesse al bordo dell’immagine, che possono essere rimosse utilizzando la funzione imclearborder.

Figura 30. Terza fase: dilatazione degli oggetti e rimozione dei bordi.

Come possiamo notare dalla figura qui sopra, la rimozione dei bordi ha come effetto anche la cancellazione dei contorni della fiala, aspetto questo, che da notevoli vantaggi in termini di attendibilità della misura. L’ultima fase dell’elaborazione consiste in uno smoothing dei contorni, che possa conferire loro un aspetto più naturale, seguito dall’eliminazione di tutte quelle aree rivelate dall’algoritmo, minori, in termini disuperficie, di un certo numero di pixel. In questo caso particolare, il limite affinché un’area

47

possa essere contata è stato fissato a 10 pixel. L’operazione appena descritta è un vero e proprio filtraggio ed è compiuto dalla funzione bwareaopen.

Figura 31. Risultato finale dell'elaborazione.

Una volta terminata l’elaborazione è possibile contare le macchie bianche rimaste, che corrispondono alle sagome delle bolle. Per far questo si utilizza il seguente comando:

[LabeledImage, numberOfBlobs]=bwlabel (I);

dove LabeledImage è una matrice e numberOfBlobs è un numero naturale che corrisponde alla quantità di aree bianche presenti nell’immagine. In questo caso l’ammontare delle bolle è pari a 36 secondo tale sistema automatizzato, e coincide col sistema di lettura manuale.

Figura 32. Immagine originale con evidenziati i punti in cui l'algoritmo ha commesso errori. L’errore in rosso evidenzia una bolla non rilevata, la blu una che invece è stata contata due

48

Come possiamo notare dalla figura 32, nonostante il conteggio effettuato meccanicamente restituisca un risultato identico a quello compiuto manualmente, esistono degli errori che avrebbero potuto influenzare negativamente la misura. In questo caso fortunatamente, le imprecisioni si sono compensate, tuttavia questo non accade sempre. Nel paragrafo seguente saranno mostrati i risultati di alcuni test preliminari compiuti per verificare l’efficienza dell’algoritmo appena visto.

Documenti correlati