• Non ci sono risultati.

7.5.1

Point cloud e eliminazione dello sfondo

Abbiamo visto nella sezione 7.3 come ho calcolato i punti 3D tramite i parametri di rettificazione e la mappa di disparit`a, fatto ci`o sono passato alla creazione della point cloud, ma che cos’`e esattamente la point cloud?

Una nuvola di punti (point cloud) `e un insieme di punti caratterizzati dalla loro posizione in un sistema di coordinate e da eventuali valori di intensit`a (colore, pro- fondit`a, ecc.) ad essi associati, nel nostro caso vediamo le coordinate omogenee dei punti che la compongono nell’equazione 7.7.

Le nuvole di punti servono, di solito, come rappresentazione di strutture tridimen- sionali come oggetti o superfici in rilievo.

In Open3D `e molto semplice passare dai punti 3D ottenuti dalla mappa di disparit`a all’”oggetto” point cloud; fatto ci`o il passaggio successivo `e stato quello di eliminare quei punti che non facevano parte del prosciutto, ovvero tutti quei punti che rap- presentavano lo sfondo, oppure degli outliers.

Per eliminare lo sfondo c’erano 2 metodi possibili:

1. Eliminare dalla mappa di disparit`a tutti quei punti che stavano al di sotto di un certo valore di disparit`a (una sorta di soglia), scelto con la logica di eliminare tutti quei punti al di sotto del valore pi`u basso che appartiene al prosciutto;

2. Utilizzare la segmentazione ottenuta tramite la rete neurale in modo da eli- minare tutti i punti che non fanno parte delle label predette e che quindi corrispondono allo sfondo.

Il primo metodo ha un problema: selezionare un valore di soglia che elimini comple- tamente lo sfondo senza per`o toccare il prosciutto `e molto difficile perch`e le disparit`a non sono omogenee in tutte le zone e inoltre anche la mappa di disparit`a `e affetta da outliers, come vediamo in figura 4.16. Il secondo metodo risolve il problema relativo al primo perch`e vengono mantenute soltanto le zone che effettivamente apparten- gono al prosciutto, ma ha un altro problema, i punti non riconosciuti dalla rete, i quali per`o appartengono fisicamente al prosciutto, vengono scartati.

Per questi motivi ho deciso di intraprendere una soluzione ”mista”, ho eliminato tutti i punti 3D non appartenenti alle label ottenute dalla segmentazione della rete (secondo metodo), i punti non riconosciuti dalla rete, ma che sono un intorno o comunque sono contornati da altri punti che invece sono stati riconosciuti, vengono comunque inseriti nella point cloud. In questo modo sono riuscito a ricostruire in 3D l’intero prosciutto.

(a) Vista a tre quarti.

(b) Vista di profilo.

Figura 7.3: Ricostruzione del prosciutto in 3D con eliminazione dello sfondo, visualizzazione tramite Open3D.

In secondo luogo ho aggiunto un controllo di soglia (primo metodo), nonostante lo sfondo fosse stato eliminato rimaneva sempre qualche outliers con disparit`a molto pi`u bassa rispetto a quella del prosciutto, per questo ho impostato una soglia molto grossolana per eliminare gli outliers molto evidenti.

In figura 7.3 vediamo il risultato finale di questo procedimento.

7.5.2

Segmentazione in 3D

Ottenuto il modello 3D del prosciutto il passaggio successivo `e quello di visualizzare in 3D anche la segmentazione ottenuta tramite la rete. Per fare ci`o baster`a modifi- care il colore dei punti che appartengono alle varie label predette dalla rete, i punti che rimarranno esclusi da tutte le label rimarranno del loro colore originale.

Come spiegato dettagliatamente nella sezione 7.4.2 in Open 3D l’oggetto PointCloud `e composto da 3 campi: PointCloud.points, PointCloud.normals, PointCloud.colors. Quindi per inserire la segmentazione nella visualizzazione 3D mi `e bastato andare a modificare il campo PointCloud.colors; ho modificato il colore dei punti della point cloud (ovviamente con un colore diverso in base alla label) che corrispondono in coordinate x,y a quelli delle label predette dalla rete, lasciando inalterati quelli che invece non corrispondevano. Il risultato `e mostrato in figura 7.4.

Come detto nel capitolo 6 la segmentazione dell’osso non `e stata possibile tra- mite la rete neurale con il database fornitomi. Questo non `e un grosso problema, i valori di disparit`a dell’osso sono molto riconoscibili perch`e decisamente pi`u alti rispetto al piano della sugna del prosciutto, come evidenziato in figura 7.3b. Per questi motivi la segmentazione dell’osso del prosciutto risulta molto pi`u facile ed `e possibile anche eseguirla nel momento in cui vengono forniti i punti 3D da sugnare al robot (in quel momento oltre ai punti appartenenti all’osso verranno esclusi anche

(a) Vista a tre quarti. (b) Vista di fronte.

Figura 7.4: Ricostruzione del prosciutto in 3D con segmentazione predetta dalla rete, visualizzazione tramite open3D.

quelli appartenenti al grasso e alla cotenna). Infatti baster`a trovare un valore di soglia di disparit`a abbastanza valido per escludere dal labeling della sugna i punti appartenenti all’osso. In figura 7.5 vediamo il labeling ottimale posto come obiettivo da raggiungere.

Figura 7.6: Esempio di retta normale a una superficie non piana in un punto.

7.5.3

Stima delle norme dei punti 3D

Il robot che dovr`a poi ”spennellare” la parte del prosciutto indicata come ”da sugna- re” ha bisogno di sapere in che modo impugnare il pennello e con che angolazione approcciarsi alla superficie per non lasciare buchi vuoti o per evitare di perdere tempo inutilmente. Per questo motivo `e indispensabile la stima delle normali alla superficie nei punti 3D calcolati.

In matematica, una normale a una superficie piana `e un vettore tridimensionale perpendicolare a quella superficie. Una normale ad una superficie non piana nel punto p su quella superficie `e un vettore perpendicolare al piano tangente a quella superficie in p, vediamo un esempio in figura 7.6.

Con la triangolazione abbiamo gi`a calcolato le coordinate z dei punti della map- pa di disparit`a in modo da poterli collocare nello spazio 3D, quindi il calcolo delle normali alla superficie totale in quei punti `e un calcolo standard e abbastanza sem- plice. Con Open3D ci`o avviene tramite la funzione estimate normals(), la quale viene ”chiamata” dall’oggetto point cloud. Lo scopo di questa funzione `e quello di calcolare le normali alla superficie in tutti i punti appartenenti alla point cloud e inserire questi vettori nella struttura dato PointCloud.normals.

Matematicamente parlando il procedimento svolto per il calcolo delle normali alla superficie nei punti `e standard: viene identificato il piano tangente alla superficie nel punto p (di cui conosco le coordinate) tramite la derivata della funzione, quindi il vettore normale `e il vettore prodotto vettoriale dei due lati non paralleli del piano tangente nel punto p.

La normale ad una superficie non ha un unico verso; il vettore che punta nel verso opposto della normale alla superficie `e anch’esso una normale a quella superficie. Per una superficie orientata, la normale alla superficie `e solitamente determinata dalla ”regola della mano destra”.

Per la visualizzazione delle normali dei punti in Open3D `e consigliato apportare un sotto campionamento alla point cloud in modo da avere meno punti e quindi una visualizzazione pi`u semplice. Per fare ci`o ho utilizzato una funzione di Open3D chiamata voxel down sample().

(a) Vista di fronte.

(b) Vista di profilo.

Figura 7.7: Point cloud sotto campionata di un 20% rispetto l’originale tramite downsample voxel.

me. Il voxel `e la controparte tridimensionale del pixel bidimensionale (che rappre- senta l’unit`a dell’area) e perci`o il volume buffer (un ampio array 3D di voxel) dei voxel pu`o essere considerato come la controparte tridimensionale del frame buffer bidimensionale dei pixel.

Nel nostro caso la definizione giusta di voxel `e: ”un punto (campione) in una griglia 3D ad intervalli regolari” Il downsampling voxel utilizza una griglia voxel regolare per creare una nuvola di punti uniformemente sotto campionata da una nuvola di punti di input. Viene spesso utilizzato come fase di pre-elaborazione per molte at- tivit`a di elaborazione delle nuvole di punti.

L’algoritmo opera in due fasi:

1. I punti vengono raggruppati in voxel;

2. Ogni voxel occupato genera esattamente un punto calcolando la media di tutti i punti all’interno.

Per quanto riguarda il mio progetto ho deciso di sotto campionare la point cloud di un 20% rispetto all’originale, in questo modo ho ottenuto il risultato in figura 7.7.

A questo punto l’ultimo passaggio di questa prima fase `e quello di visualizzare le normali calcolate precedentemente con la funzione estimate normals(). Nell’inter- faccia grafica di Open3D per mostrare le normali nei punti basta premere il tasto n durante la visualizzazione. Nel nostro caso il risultato `e quello di figura 7.8.

(a) Vista di fronte.

(b) Zoom centrale.

Figura 7.8: Point cloud sotto campionata di un 20% rispetto l’originale tramite downsample voxel, con visualizzazione delle normali.