• Non ci sono risultati.

Riconoscimento delle specie ittiche

N/A
N/A
Protected

Academic year: 2021

Condividi "Riconoscimento delle specie ittiche"

Copied!
61
0
0

Testo completo

(1)

Studente/i

Giovanni Converso

Relatore

Salvatore Vanini

Correlatore

-Committente

Salvatore Vanini

Corso di laurea

Ingegneria Informatica

Modulo

Progetto di diploma

Anno

2018/2019

Data

(2)
(3)

Indice

1 Abstract 1 2 Introduzione 3 2.1 Descrizione progetto . . . 3 2.2 Compiti . . . 3 2.3 Obiettivi . . . 3 3 Architettura Logica 5 4 Modello 7 4.1 TensorFlow . . . 7 4.1.1 Installazione . . . 7 4.2 Keras . . . 7 4.3 Rete Convoluzionale . . . 8 4.3.1 Tensore . . . 8 4.3.2 Nodo . . . 9 4.3.3 Livelli . . . 10

4.3.4 Meccanismo di una rete Convoluzionale . . . 13

4.4 Fish Classifier . . . 17

4.4.1 Re-Train vs Creazione . . . 18

4.4.2 Struttura del modello . . . 18

4.4.3 Fit del modello . . . 19

4.4.4 Parametri di fit del modello . . . 20

4.4.5 Salvataggio del modello . . . 21

4.4.6 Utilizzo del modello . . . 21

4.4.7 Specie ittiche riconosciute . . . 21

4.4.8 Risultati . . . 22

5 Server 23 5.1 Servizio REST . . . 23

(4)

5.4 PostgreSQL . . . 26 5.4.1 Servizi di PostgreSQL . . . 27 5.4.2 Utilizzo . . . 28 5.4.3 Struttura del DB . . . 29 5.5 Comunicazione Client-Server . . . 29 5.5.1 Https . . . 30 5.5.2 Mapping . . . 31 5.6 Funzioni di Encryption . . . 35 5.7 Unit test . . . 35 5.8 Librerie installate . . . 35 6 Client 37 6.1 Ionic . . . 37 6.1.1 Installazione . . . 37 6.1.2 Principali comandi . . . 38 6.2 Pagine . . . 38 6.2.1 Tabs . . . 38 6.2.2 Login . . . 42 6.2.3 Register . . . 43 6.2.4 Change password . . . 44 6.3 Async Function . . . 45 6.4 Richieste al server . . . 46 6.5 CameraPreview plugin . . . 46

6.6 Native Storage per la sessione . . . 47

6.7 Unit Test . . . 47 7 Metodo AGILE 49 8 Conclusioni 53 8.1 Risultati . . . 53 8.2 Sviluppi futuri . . . 53 Allegati 55

(5)

Capitolo 1

Abstract

Italiano

Il progetto descritto in questo documento si inserisce nel contesto dei sistemi di classifica-zione, in particolare dell’apprendimento supervisionato di specie ittiche. Lo scopo è quello di implementare una piattaforma che, attraverso l’uso di un dispositivo mobile, consenta di scattare una fotografia ad un pesce riconoscendone la specie attraverso un classificatore precedentemente addestrato. E’ stata sviluppata una rete convoluzionale in grado di rico-noscere tredici specie ittiche. Il modello creato e addestrato è reso disponibile in modo esclusivo ad un server creato ad hoc che espone un servizio REST. Inoltre, è stata imple-mentata un’applicazione client per comunicare con il server. Il client in questione permette all’utente finale di potersi registrare e autenticare nella piattaforma, fotografare il pesce e memorizzare la foto con le relative informazioni, in un album privato dedicato. I risultati ottenuti sono soddisfacenti, in quanto soddisfano tutti i requisiti richiesti dal committente, lasciando spazio per ulteriori migliorie.

(6)

species through a previously trained classifier. A convolutional neural network was deve-loped which is able to recognize thirteen fish species. The created and trained model is available exclusively to a custom created server that exposes a RESTful web-service. Fur-thermore, a client application to communicate with the server was implemented. The client in question allows end users to register and authenticate to the platform, take pictures of a fish and store the picture with the related information, in a dedicated private album. Ob-tained results are satisfactory, as they meet the requirements of the commissioning client, leaving room for further improvements.

(7)

Capitolo 2

Introduzione

2.1

Descrizione progetto

Si vuole realizzare il prototipo di un sistema per il riconoscimento, la catalogazione e la consultazione di immagini.

Più precisamente, le immagini che si vorrebbero classificare sono relative a specie ittiche. Le immagini vengono acquisite tramite un’apposita app. Esse vengono inviate ad un server che effettua la classificazione, le cataloga e quindi le archivia. E’ possibile consultare le foto caricate tramite la stessa app. Si vuole quindi creare un album digitale personalizzato, in cui ogni utente può vedere la propria lista di immagini caricate, la specie fotografata e la data.

2.2

Compiti

• Eseguire e discutere l’analisi con il docente

• Valutare le tecnologie e proporre diverse soluzioni

• Documentarsi sulle tipologie di neural networks per la classificazione di immagini

• Progettare l’app che consente di scattare le foto, caricarle sull’archivio e consultarle

• Progettare il modulo per la classificazione delle immagini

• Progettare il database per l’archiviazione delle immagini

2.3

Obiettivi

• Implementare il sistema completo (app + backend) che soddisfa i requisiti di progetto

• Acquisire delle conoscenze di base sulle neural networks e sul loro impiego per la classificazione di immagini

(8)
(9)

Capitolo 3

Architettura Logica

La piattaforma creata in questo progetto comprende una parte server che ha libero accesso al modello creato per il riconoscimento delle specie ittiche con cui esso è stato addestrato, gestisce l’interazione tra client e un database in cui vengono persisti gli utenti registrati e le immagini da loro scattate. Il client gestisce un file proprio in cui viene memorizzata la sessione in modo da non chiedere l’autenticazione nel caso in cui l’utente non ha chiesto esplicitamente il logout.

(10)
(11)

Capitolo 4

Modello

4.1

TensorFlow

TensorFlow è una libreria software open source che fornisce una piattaforma per il machine learning. Pubblicato il 9 Novembre 2015, vanta una grande community e una buona do-cumentazione che gli permette di essere la libreria più scelta rispetto ai suoi rivali Theano, PyTorch, Keras e Caffe.

Utilizzato sia in ambito accademico sia nella ricerca scientifica possiede modelli già imple-mentati robusti e ben testati per molteplici impieghi. Le API native sono scritte in Python e C++.

4.1.1

Installazione

Per installare la libreria è stato utilizzato il pip manager eseguendo il comando: p i p i n s t a l l t e n s o r f l o w

che ha effettuato il download della release CPU-only. E’ possibile scaricare anche la ver-sione GPU che garantisce maggiori performance. Il linguaggio utilizzato per usufruire delle funzioni della libreria è python.

import t e n s o r f l o w as t f

4.2

Keras

Come TensorFlow è una libreria open source per l’apprendimento automatio e le reti neurali, con la differenza di avere un’interfaccia di un livello di astrazione maggiore che supporta come back-end altre librerie a lei simile come TensorFlow, Theano e Microsoft Cognitive Toolkit. TensorFlow include al suo interno keras, quindi non è necessario installare pacchetti esterni:

(12)

e tutti i parametri ad esso associato da tenere in considerazione per poter personalizza-re il classificatopersonalizza-re in base alle proprie esigenze. La struttura del classificatopersonalizza-re cpersonalizza-reato per FishClassifier verrà argomentata nei capitoli successivi.

4.3

Rete Convoluzionale

La rete neurale convoluzionale (CNN) è un set di algoritmi usati principalmente per la classi-ficazione di immagini, cluster di immagini simili (per la ricerca di foto) e per il riconoscimento di oggetti, volti e scene. La rete può essere costituita da decine o centinaia di livelli, dove ogni livello contiene dei nodi che possono essere differenti in base al livello in cui si trovano. Ogni livello impara a rilevare diverse feature di un’immagine prendendo in input un frammen-to di immagine originale, o precedentemente elaboraframmen-to da un altro livello, fornendo in output lo stesso frammento filtrato. Come si evince quindi il flusso dei dati di questa rete è di tipo sequenziale e per questo motivo fa parte delle Feedforward Networks. E’ possibile creare una CNN da zero o riaddrestrarne una già esistente con il proprio dataset. Bisogna prestare attenzione a come disporre i livelli, perché la rete convoluzionale per essere definita tale ha un pattern sull’ordinamento dei livelli da seguire (capitolo 4.3.3)

4.3.1

Tensore

Una rete convoluzionale accetta e processa immagini sotto forma di tensori che non sono altro che una matrice multidimensionale. Un’immagine è una matrice tridimensionale di pixel dove la dimensione è caratterizzata dalla sua risoluzione e dal numero di canali (RGB). Un’immagine di input del modello avrà questa forma:

(13)

4.3.2

Nodo

L’elemento base della rete è il nodo. Esso è il luogo in cui avviene la computazione e, come il neurone dell’essere umano, viene attivato quando incontra stimoli sufficienti. Un nodo combina l’input con una serie di coefficienti che modificano quell’input in modo da avere come output un valore che indica quanto esso è utile per classificare i dati senza errore. Tutti gli input di un nodo vengono sommati e il risultato è passato alla funzione di attivazione del nodo (che non può essere diverso tra nodi dello stesso livello) che determina se e in che misura tale segnale debba progredire attraverso la rete per influenzare il risultato finale. Se i segnali passano si dice che il neurone è stato “attivato”.

Le principali funzioni di attivazione sono:

• ELU: Exponential Linear Unit tende a far convergere i costi a zero più velocemente e produce risultati più accurati. Differentemente dalle altre funzioni di attivazione la ELU ha un valore aggiuntivo alpha che dovrebbe essere positivo. E’ in forma di funzione di identità per input non negativi, e per input negativi converge quando il suo output è -alpha

• ReLU: Rectified Linear Units corrisponde a max(0, Z). A differenza della ELU non produce output negativi. Il comportamento è molto simile al Sigmoid ma con migliori performance data la sua semplicità computazionale. Essa dovrebbe essere utilizzata solo in nodi di livelli intermedio. In alcuni casi può causare un aggiornamento del pe-so sbagliato provocando la “morte” del neurone (questo avviene nell’area dove x<0) perché il gradiente* assumera il valore 0 (nulla è cambiato) e quindi il neurone entra in uno stato in cui smetterà di rispondere alle variazioni di errore/input. Esiste Lea-kyReLU che risolve questo problema permettendo una piccola variazione di f(x) per x<0.

(14)

• Sigmoid: Prende un valore reale come input e genera un altro valore tra 0 e 1. Risponde alla funzione

f (x) = 1 1 + e−z

• Softmax: Assegna ad ogni classe target la probabilità che l’input appartenga ad essa. Queste probabilità sono quelle ritornate come output dal modello. L’ultimo livello del modello quindi avrà nodi con questa funzione di attivazione.

4.3.3

Livelli

In un modello vengono mescolati diversi tipi di livelli e ciò che è importante è l’ordine in cui questi vengono posti. In una rete convoluzionale è presente un pattern strutturale da seguire che è quello di creare un livello convoluzionale, uno di pooling e uno fully-connected. Essi possono essere ripetuti più volte ma ciò che è fondamentale è che deve essere rispettata la disposizione reciproca sopra-esplicitata.

(15)

Convolutional Layer - The Kernel: E’ il primo livello incontrato dall’immagine da

filtrare. Esso fa uso di un kernel utile per porre un primo filtro all’immagine. Si prende come esempio una matrice 5x5x1 e gli si vuole applicare un filtro 3x3x1 come di seguito:

Il kernel scannerizza passo passo la matrice sommando il prodotto tra i valori della matrice filtro con i valori della matrice da filtrare, salvando il risultato nella matrice risultante.

Si arriverà ad avere una matrice risultante che costituisce la matrice filtrata (la dimen-sione varia in base alla matrice di input, è un caso che nell’esempio precedente ha la stessa dimensione del kernel). Un’immagine viene filtrata in modo analogo appli-cando però 3 kernel uno per ogni canale e il risultato di ogni singolo canale viene sommato:

(16)

Questo livello permette l’estrazione di features di alto livello come ad esempio gli spigoli di oggetti presenti nell’immagine, ciò però non è sufficiente per definire un classificatore robusto. A tale proposito devono essere aggiunti altri 2 tipi di livelli che completano il lavoro del livello convoluzionale.

Pooling Layer: Similmente al lavoro svolto dal livello convoluzione, il livello di pooling

è responsabile della riduzione della dimensione del tensore in modo da decrementare la potenza computazionale richiesta per processare i dati. Inoltre è molto utile per l’e-strazione di features che non cambiano in caso di rotazione o posizione; un’immagine ruotata dovrà dare quindi un risultato pressoché simile. Come il layer convoluzionale viene utilizzato un kernel che definisce il tipo di pooling da eseguire che può essere: Max Pooling o Average Pooling. Nel primo caso viene ritornato il massimo valore della porzione coperta dal kernel, nel secondo caso viene fatta una media. In genere il Max Pooling è l’operazione più performante perché riduce il rumore, aspetto che invece l’Average non possiede.

(17)

I due livelli appena descritti se posti in modo alternato permettono al classificatore di apprendere features caratteristiche dell’immagine. Più complessa sarà l’immagi-ne maggiore sarà il numero di livelli Convoluzionali e di Pooling da utilizzare con la conseguenza di maggiore tempo di calcolo da sostenere.

Fully-Connected Layer: L’utilizzo di questo livello è fondamentale per definire la

clas-se target a cui quei pattern rilevati nelle fasi precedenti appartengono. In faclas-se di ad-destramento del modello, nel corso di una serie di epoche il modello è in grado di distinguere tra caratteristiche dominanti e non dominanti, classificandole utilizzando la tecnica di Softmax.

4.3.4

Meccanismo di una rete Convoluzionale

Dopo aver descritto i layers principali messi a disposizione da keras, è utile comprende-re come questi insieme elaborano un’immagine in input. Si consideri una situzione molto

(18)

semplice in cui bisogna distinguere un ‘/’ da un ‘\’ in immagini con risoluzione 2x2 come qui sopra.

Bisogna trovare un’operazione per cui la macchina è in grado di distinguere questi due label. Si utilizza un kernel “incrociato”:

da moltiplicare con la matrice input. Si avrà quindi un valore negativo (-4) che indica l’appartenza alla classe ‘/’ e un valore positivo (+4) per la classe ‘\’.

Dopo aver definito un’operazione utile e performante per il riconoscimento della classe di appartenenza, il classificatore è pronto a predire una nuova matrice in input.

In questo primo esempio viene applicato lo stesso kernel e il risultato ottenuto è un numero positivo (+2) quindi il modello lo classificherà come ‘\’

In questo secondo esempio invece il risutato è negativo (-2) e la matrice sarà classifica-ta come ‘/’. Queste sono le principali operazioni, spiegate a grandi linee, svolte da un classificatore. La parte più complessa è scegliere il kernel più adatto.

(19)

In questo esempio le possibili combinazioni di kernel sono 6 = 24(2 possibili valori, per 4 pixels), ma in un caso reale la risoluzione è nettamente maggiore. La scelta del kernel migliore avviene in modo randomico: ne viene scelta una possibile opzione e viene creato un albero dove ogni nodo è un kernel con alcune modifiche rispetto al nodo padre.

Accorgendosi che il kernel più appropriato è quello "incrociato" visualizzato prima.

Supponiamo ora di avere un caso leggermente più complesso, in cui la risoluzione è 3x3 e si vuole poter distinguere 4 caratteri ‘/’, ‘\’, ‘X’, ‘O’.

Dalla situazione più semplice siamo a conoscenza dei filtri per il back-slash e quelli per il forward-slash con dimensione 2x2. Anche in questo caso essi dimostrano un’utilità non indifferente.

(20)

In questo caso la matrice in input viene filtrata nel primo livello (Convolutional) con il kernel specificato e nel secondo livello (Pooling) viene detettato quali pattern sono stati trovati; nella prima scrematura è possibile evidenziare i due back-slash, nella seconda invece due forward-slash.

L’output di questi due livelli corrisponde ai dati di ingresso del livello Fully-Connected, dove vengono creati dei filtri utili alla comparazione tra la matrice da predire e le classi con cui il modello è stato addestrato, per poter poi definire la classe di appartenenza.

L’immagine in input:

• viene filtrata con i due kernel visti

• la matrice risultante viene appiattita

• viene creato un filtro in fase di fit che verrà utilizzato poi per la predizione.

(21)

In versione molto semplificata è questo il lavoro di una rete convoluzionale. Il compito dello sviluppatore è quello di trovare i giusti parametri di configurazione:

• Numero di livelli Convoluzionali/Pooling

• Numero di nodi per livelli

• Dimensione dei kernel per il filtraggio dell’immagine

• Passo di spostamento del kernel (chiamato stride)

• Tipo di ottimizzatore

• La funzione di loss

• La dimensione dei batch

• Le epoche

4.4

Fish Classifier

L’obiettivo del progetto, come già detto, è quello di creare un classificatore che riesca a riconoscere (per ora) un numero abbastanza ristretto di specie ittiche. Ci sono due tecni-che per l’apprendimento automatico: apprendimento supervisionato e apprendimento non supervisionato. E’ stata usata la prima versione che mira a istruire un modello ad elabo-rare automaticamente previsioni sui valori di uscita di un sistema, fornendogli dati in input; questo sulla base di una serie di esempi costituiti da input e output inizialmente forniti. Gli algoritmi di apprendimento supervisionato lavorano in due fasi:

(22)

4.4.1

Re-Train vs Creazione

E’ possibile fare uso di reti già create oppure crearne una nuova. Il vantaggio di riaddrestra-re un modello già esistente priva lo sviluppatoriaddrestra-re di averiaddrestra-re un carico di lavoro non indifferiaddrestra-rente legato alla costruzione da zero che richiede un’approfondita conoscenza nel campo, quindi i tipi di livelli da utilizzare e le diverse configurazioni. Non è presente una versione miglio-re dell’altra, i vantaggi sono evidenti in base al bisogno. Cmiglio-reando una miglio-rete da zero si ha il pieno controllo, si ha la sicurezza di avere un modello ad-hoc per la propria situazione e se ben implementata può produrre risultati impressionanti. In sede di scelta si deve te-nere conto che per questa ultima tecnica però bisogna disporre di un numero maggiore di immagini in fase di addestramento per permettere alla rete di creare input più accurati ai singoli nodi, come ad esempio il peso da assegnare a ciascuno di essi. Differentemente nella tecnica di re-train i nodi hanno già un peso associato e quelli che vengono addestrati sono sostanzialmente gli ultimi livelli permettendo di avere come output le classi target che si vogliono ottenere. E’ stato deciso di intraprendere la strada più complessa alla ricerca di un risultato ottimale, iniziando con il riconoscimento di 4 specie abbastanza distinguibili per poi aumentare graduatamente con il numero di classi target.

4.4.2

Struttura del modello

Il modello come già detto è di tipo sequenziale. I livelli aggiunti sono:

(23)

Tipo 64 N. nodi Kernel/Pool size Funz. Attivazione Conv2D 64 3x3 relu MaxPooling 2x2 BatchNorm Conv2D 96 3x3 relu MaxPooling 2x2 BatchNorm Conv2D 128 3x3 relu MaxPooling 2x2 BatchNorm Conv2D 128 3x3 relu MaxPooling 2x2 BatchNorm Conv2D 96 3x3 relu MaxPooling 2x2 BatchNorm Conv2D 96 3x3 relu MaxPooling 2x2 BatchNorm Dropout(0.2) Flatten Dense 256 relu Dropout(0.2) Dense 128 relu Dropout(0.3) Dense 13 softmax

4.4.3

Fit del modello

Allenare una rete neurale significa trovare i giusti pesi associati ad ogni nodo in modo da massimizzare la verosimiglianza tra i dati predetti ed i dati reali. Come detto in preceden-za lo svantaggio di creare un modello da zero è quello di avere a disposizione un numero maggiore di immagini per il fit. Un grosso problema incontrato è stata la ricerca di un data-set consistente che fornisse molteplici immagini di ogni singola specie. Utilizzando lo script google_images_download.py è stato possibile crearsi un proprio dataset scaricando imma-gini direttamente da Google Images. Sono stati scaricati circa un centinaio di foto per specie prendendone l’80% per il train e il rimanente 20% per il test set utile per valutare il modello. E’ stato utile aumentare il numero di immagini in fase di train creando nuove figure risultanti da operazioni di modifica quali rotazione, specchiamento, sfocatura e traslazione. Questa appena specificata è una tecnica molto utilizzata per affinare il modello. Nonostante questo

(24)

Gli algoritmi di apprendimento supervisionato necessitano di uno strumento per misurare la bontà delle predizioni in funzione dei parametri del modello, così da poterli modicare e migliorare la bontà della predizione. Le funzioni di perdita (loss function) sono il metodo utilizzato in fase di training per valutare quanto le previsioni del modello siano verosimili. Esi-stono diverse loss function che misurano la discrepanza tra valori reali e valori predetti, ma il tipo di loss scelta influenza completamente la futura bontà del modello. Essa deve essere definita in base al tipo di problema. Inoltre essa ci permette di introdurre termini di regola-rizzazione in modo tale da poter penalizzare alcuni errori e conseguentemente modificare ciò che il modello apprende. Bisogna considerare che il modello in fase di apprendimento lavora sempre e solo sul training set, di conseguenza c’è il rischio che appende valori che vanno a interpolare le features estratte senza generalizzare. In questo modo perde la capa-cità di generalizzazione e memorizza il training set. Questa condizione è conosciuta come overfitting che deve essere prevenuta. I principali tipi di loss sono:

Mean Squarred Error: E’ la funzione di default per problemi di regressione. La media

quadratica è calcolata come la media del quadrato della differenza tra il valore predetto e quello effettivo. Il risultato è sempre positivo indipendentemente dal segno dei valori previsti e un valore perfetto è lo 0,0. La funzione penalizza errori più grandi perché avranno un valore maggiore.

Binary CrossEntropy

Categorical CrossEntropy: E’ la più utilizzata nel caso di classificazione multi-classe.

Matematicamente è quella più adatta a qualsiasi tipo di problema. Calcola un punteg-gio che sintetizza la differenza media tra le distribuzioni di probabilità effetive e previste per tutte le classi del problema. E’ la variante multiclasse della Binary CrossEntropy. E’ la funzione utilizzata nel modello creato.

OPTIMIZERS

Gli algoritmi di ottimizzazione aiutano a minimizzare (o massimizzare) una funzione obietti-vo. Le due ottimizzazioni che si eseguono di solito sono la minimizzazione della loss function o la massimizzazione dell’accuratezza. I principali tipi sono:

Gradient Descend (e le sue varianti)

E’ l’algoritmo principale per minimizzare la loss function. Applica operazioni di deriva-zione perché le funzioni diminuisco maggiormente verso il valore più alto del proprio gradiente. E’ un algoritmo iterativo.

(25)

Adam

Adaptive Moment Estimation è un metodo che calcola i tassi di apprendimento adat-tivo per ciascun parametro. E’ tra i migliori per l’apprendimento adatadat-tivo in quanto converge molto velocemente. E’ l’algoritmo utilizzato nel modello che è stato creato.

EPOCHS E BATCH SIZE

In fase di addestramento si ha il bisogno di allenare il modello con tutto il training set, ma ciò è limitato dalla memoria dei calcolatori. Ciò che si fa è dividere il set in più parti (batch) usan-do queste porzioni di dataset per addestrare tutto il modello (dal primo livello fino all’ultimo) per più volte (epochs) ed ad ogni iterazione i pesi vengono aggiornati.

4.4.5

Salvataggio del modello

Dopo aver definito il tutto, con la funzione MyModel.save(‘NomeDelModello.model’) è possi-bile salvare la configurazione del modello allenato che potrà essere poi utilizzato nella fase di predizione della specie.

4.4.6

Utilizzo del modello

Dopo aver salvato il modello sotto formato .model è possibile chiamare il metodo messo a disposizione da keras tf.keras.models.load_model(‘NOMECLASSIFICATORE.model’). Do-po aver caricato il modello è Do-possibile chiamare il metodo .evaluate passando il testset precedentemente creato ottenendo la percentuale di accuratezza.

Per fare una singola predizione bisogna:

• Definire un array composto dalle classi da identificare

• Caricare l’immagine

• Convertirla in scala di grigi

• Ridimensionarla con la stessa dimensione con cui il modello è stato addestrato

• Chiamare il metodo .predict del numpy array creato:

np . a r r a y ( t o _ p r e d i c t ) . reshape (−1 , IMG_SIZE , IMG_SIZE , 1 ) La funzione ritorna un array dove ogni elemento corrisponde alla probabilità che l’immagine da classificare appartenga alla classe target posizionata nello stesso indice. Prendendo l’elemento con valore maggiore si ha la predizione della specie

4.4.7

Specie ittiche riconosciute

Come detto, il numero di specie riconosciute sono 13, alcune simili tra loro per verificare la consistenza del modello.

(26)

• acipenser: storione

• mullus: triglia

• perca: pesce persico

• sardina: sardina • scomber: sgombro • solea: sogliola • sparusaurata: orata • thunnus: tonno • trisopterus: merluzzo

4.4.8

Risultati

Il modello è stato addestrato in 20 epoche con 50 immagini a batch. A fine addestramento l’accurancy ha raggiunto quasi il 93% e la loss 0.2195.

Ora il modello è utilizzabile per poter classificare nuove immagini di pesci appartenenti alle specie con cui esso è stato addestrato.

(27)

Capitolo 5

Server

Il modello appena addestrato sarà disponibile direttamente solo ed esclusivamente al server che vi effetuerà la classificazione quando il client chiederà di farlo. Si è scelto di utilizzare un server per due motivi:

• Liberare il client dalla complessità di tensorflow

• Avere un nodo centrale interrogabile

• Determinare chi può utilizzare tale servizio

In particolare il server sviluppato espone un servizio REST. Attualmente, per motivi di svi-luppo, il server gira localmente all’indirizzo 0.0.0.0:5000 in modo da essere rintracciato da tutti gli host collegati alla stessa rete, digitando <ip-server>:5000 .

5.1

Servizio REST

REST (Representetional State Transfer) definisce un insieme di principi architetturali per la progettazione di un sistema. Non si rifierisce ad un sistema concreto né standardizzato. REST segue 5 principi:

• Identificazione delle risorse

• Utilizzo esplicito dei metodi http

• Risorse autodescrittive

• Collegamenti tra risorse

(28)

5.2.1

Installazione

E’ facilmente installabile da pip package manager con il comando: p i p i n s t a l l f l a s k

5.2.2

Utilizzo

Importando Flask nel proprio script è possibile creare un web server facile e robusto. Sul sito ufficiale viene descritto un esempio iniziale utile a far comprendere la semplicità di Flask:

from f l a s k import Flask , escape , r e q u e s t

app = F l a s k ( __name__ )

@app . r o u t e ( ’ / ’ )

def h e l l o ( ) :

name = r e q u e s t . args . g e t ( " name " , " World " )

r e t u r n f ’ H e l l o , { escape ( name ) } ! ’

Come è possibile notare viene definito un mapping interrogabile. Quindi quando un client digiterà <ipserver>:5000, verrà ritornata la stringa “Hello, <nome inserito nella richiesta”. Se si volesse rispondere esclusivamente ad una richiesta POST la modifica da apportare sarebbe solo in:

@app . r o u t e ( ’ / ’ , methods = [ POST ] )

5.3

Token-Based Authentication

Il sistema di autenticazione utilizzato è quello basato su token, in particolare JWT (JSON Web Token) definito dallo standard RFC 7519.

5.3.1

Token

Il token non è altro che una stringa che codifica una serie di informazioni. Per la codifica è utilizzata una SECRET_KEY che deve essere conosciuta solo da chi crea il token in modo da poterlo poi decodificare a posteriori. E’ divisa in tre parti:

(29)

Header

Dichiara che l’oggetto codificato è un token Web JSON e che è stato codificato con l’algoritmo SHA-256

Payload

Sono metadati aggiunti che incrementano la sicurezza rendendo più ostica la decodi-fica da entità estranee. E’ anche dove vengono digitate le informazioni da scambiarsi con il client. Ad esempio all’interno del payload è stato condiviso l’utente che effettua la richiesta al server in modo da permettere al server di eseguire query nel database avendo a dispozione l’username.

Signature

Sono delle specifiche per la firma finale del token.

Dato un token è possibile visitare jwt.io e decodificarlo, per verificarlo bisogna specificare la SECRET_KEY all’interno della signature.

5.3.2

Utilizzo

Si necessità avere URI protetti e utilizzabili solo da coloro che possiedono un token. La generazione del token avviene solo una volta durante la registrazione dell’utente. Il token rimane statico e non viene mai modificato. La crezione avviene in questo modo lato server:

(30)

possibile generare token con scadenza regolare specificando il timestamp nei parametri della funzione di creazione, ma per comodità è stato scelto di non attribuirgliela. Il vantaggio più grande è quello di non dover passare la password ad ogni richiesta che poi dovrebbe essere verificata accedendo al database; con un token valido il problema non si pone. Viene fatta la convalida del token e solo in caso afffermativo si prosegue con la richiesta. Un pattern utilizzato a questo scopo è il decorator, la funzione decoratrice ha questo aspetto:

def t o k e n _ r e q u i r e d ( f ) :

@wraps ( f )

def d e c o r a t e d (∗args , ∗∗kwargs ) : to ken = None

i f r e q u e s t . headers [ ’ Content−Type ’ ] == ’ a p p l i c a t i o n / j s o n ’ : j s o n O b j = j s o n . l o a d s ( j s o n . dumps ( r e q u e s t . j s o n ) ) i f not j s o n O b j : r e t u r n j s o n i f y ( { ’ message ’ : ’JSON i s m i s s i n g ’ } ) , 403 to ken = j s o n O b j [ " to ken " ] i f not token : r e t u r n j s o n i f y ( { ’ message ’ : ’ Token i s m i s s i n g ’ } ) , 403 t r y :

data = j w t . decode ( token , app . c o n f i g [ ’SECRET_KEY ’ ] )

except :

r e t u r n j s o n i f y ( { ’ message ’ : ’ Token i s i n v a l i d ’ } ) , 403

r e t u r n f (∗args , ∗∗kwargs )

r e t u r n d e c o r a t e d

Il nome della funzione appena descritta deve essere specificata sopra la funzione che gestisce il mapping e che richiede l’utilizzo del token:

@app . r o u t e ( ’ / saveImage ’ , methods = [ ’POST ’ ] ) @token_required

def saveImage ( ) :

5.4

PostgreSQL

PostgreSQL è un potente sistema di database relazionale ad oggetti open source che utiliz-za ed estende il linguaggio SQL combinato con molte funzionalità che memorizutiliz-zano e

(31)

ridi-mensionano in modo sicuro i carichi di lavoro di dati più complicati. Le origini di PostgreSQL risalgono al 1986 come parte del progetto POSTGRES presso l’Università della California a Berkeley e ha oltre 30 anni di sviluppo attivo sulla piattaforma principale. Ha guadagnato una solida reputazione per la sua architettura, affidabilità, integrità dei dati, estensibilità e per la sua vasta comunità open-source utile a fornire costantemente soluzioni performanti e innovative. Nel 2001 è diventato conforme alle operazioni ACID.

5.4.1

Servizi di PostgreSQL

La vastità di operazioni disponibili in postgres sono utilizzabili sia da linea di comando (psql), sia graficamente (pgAdmin4).

psql

è un front-end basato su terminale per PostgreSQL. Consente di digitare le query in modo interattivo, inviarle a PostgreSQL e visualizzarne il risultato. Inoltre, fornisce una serie di meta-comandi e funzioni shell-like per facilitare la scrittura di script.

pgAdmin4

E’ un runtime desktop creato utilizzando Python e javascript/jquery. L’applicazione viene distribuita su un server Web accessibile dal proprio browser. Permette di ese-guire quasi tutte le operazioni fattibili anche in psql, con la differenza di avere una dashboard utile a monitorare parametri dei database in funzione.

(32)

5.4.2

Utilizzo

Python ha diversi driver per utilizzare PostgreSql, il più popolare èpsycopg che implementa

completamente la specifica Python DB-API 2.0. La versione utilizzata è l’ultima, psycopg2. L’adapter per il database è implementato in C risulta veloce e sicuro. Tra le funzioni più note ricordiamo cursor lato client e lato server, notifiche e comunicazioni asincrone (ecc. . . ). Per l’utilizzo bisogna seguire una scaletta:

• Specificare la configurazione del server che ospita il database (viene definita una sola volta ed è statica)

con = psycopg2 . connect ( h o s t = " l o c a l h o s t " , database = " t e s t " , user = " p o s t g r e s " ,

password = f . d e c r y p t ( passw_postgres ) . decode ( ) )

• Ogni volta che si ha il bisogno di interrogare il database aprire ed eseguire un cursor dalla connessione

c u r s o r = con . c u r s o r ( )

c u r s o r . execute ( " SELECT ∗ from us er s WHERE username = ’%s ’ " % ( user , ) ) (in questo caso la query ritorna un array bidimensionale; il numero di righe è dato dal

numero di oggetti all’interno del database che hanno come username “mario”). Per ottenere il risultato bisogna eseguire la funzione:

(33)

row = c u r s o r . f e t c h a l l ( )

• Dopo ogni query bisogna committare le modifiche (nel caso in cui la query appena eseguita fosse un’operazione di modifica) e chiudere il cursore

con . commit ( ) c u r s o r . c l o s e ( )

• Alla fine del programma chiudere la connessione con . c l o s e ( )

5.4.3

Struttura del DB

Per il progetto sono servite due tabelle, una adibita alla memorizzazione dei dati riferiti al singolo utente (quali id, username, password criptata, token criptato e il flag che indica se l’utente è loggato) e una per le immagini (con id dell’utente come chiave esterna, un array di byte per persistere le immagini, la data in cui la foto è stata scattata e la specie predetta).

Users:

CREATE TABLE us er s (

i d BIGSERIAL NOT NULL PRIMARY KEY,

username VARCHAR( 3 0 0 ) NOT NULL , password VARCHAR( 3 0 0 ) NOT NULL , to ken VARCHAR( 3 0 0 ) NOT NULL , logged boolean

) ;

Images:

CREATE TABLE images (

u_image BYTEA NOT NULL , u _ i d BIGINT ,

d a t e t i m e t e x t ,

type VARCHAR( 3 0 0 ) ,

FOREIGN KEY ( u _ i d ) REFERENCES u se rs (i d )

) ;

5.5

Comunicazione Client-Server

Come detto in precedenza il server non ha un indirizzo pubblico, ma privato. E’ raggiungibile solo in locale digitando l’ip locale dell’host che esegue lo script in python del server.

(34)

chiave:

• Autenticazione del sito web visitato

• Protezione della privacy (riservatezza e confidenzialità)

• Integrità dei dati scambiati tra le parti comunicanti

Per implementare una comunicazione https in flask ci sono vari metodi:

• Un metodo ad-hoc (che genera delle chiavi on-fly diverse per ogni connessione)

• Self-Signed Certificates (quella utilizzata)

• Un metodo per Web Server usato in produzione (richiede un dominio)

Self-Signed Certificates

Il certificato autofirmato è quello in cui la firma viene generata utilizzando la chiave privata associata allo stesso certificato. Questo significa che nessuna CA (Certifcation Authority) ha firmato con la propria chiave, questo è il motivo per cui se si volesse accedere ad un URI il browser fornirà questa warning:

Tale messaggio comunica all’utente che il sito non è convalidato con le chiavi dell’ente di certificazione e l’utente può decidere di proseguire a suo rischio e pericolo. Per generare le chiavi auto-firmate bisogna installare il pacchetto openssl:

(35)

e digitare il comando:

o p e n s s l req −x509 −newkey r s a :4096 −nodes −o u t c e r t . pem −k e y o u t key . pem

−days 365

dove -days indica la validità delle chiavi in termini di tempo. Il comando appena esegui-to chiederà maggiori informazioni sull’ente che richiede le chiavi in modo da comunicare all’utente finale le origini del server (Organization Name, Email Address, Country Name ecc. . . ) Dopo aver generato le chiavi ed averle auto-firmate, nel server, come parametro della funzione run(), bisogna specificare il contesto ssl:

app . run ( h o s t = ’ 0 . 0 . 0 . 0 ’ , s s l _ c o n t e x t = ( ’ c e r t . pem ’ , ’ key . pem ’ ) ) Il risultato sarà avere una connessione https in cui l’utente ha la possibilità di sapere chi gestisce i dati inviati a quel server:

5.5.2

Mapping

Essendo un servizio REST i servizi messi a disposizione del server sono tutti mappati in URI differenti. Di seguito verranno elencati i parametri necessari affinchè ogni richiesta sia convalidata dal server e verranno elencate le possibili risposte. Per ogni map il server risponderà adeguatamente alle richieste POST, facendo una richiesta GET l’utente verrà

(36)

" username " : " xxxx " , " password " : " xxxx " }

Se l’username è già presente all’interno del DB il server risponderà con codice 205 (reim-posta contenuto) e con il seguente messaggio:

{ ’ message ’ : " User a l r e a d y e x i s t " }

Altrimenti in caso di convalida della richiesta il server comunicherà il token generato con codice 201 (creato):

{ " t oke n " : " xXyYzzzZ . . . " }

/login

Permette all’utente registrato di poter accedere ai servizi esposti dal server. Body da specificare:

{

" username " : " xxxx " , " password " : " xxxx " }

Risposta: Se l’username specificato non esiste nel database, 401(accesso negato): { ’ message ’ : ’ Wrong username ! ’ }

Se l’username è corretta e la password no, 401(accesso negato): { ’ message ’ : ’ Wrong password ! ’ }

Altrimenti se i parametri sono corretti, 200 (OK): {

’ message ’ : ’ Logged ’ , ’ t oke n ’ : ’ xxxYxXZZz ’ }

/logout

Permette la terminazione della sessione, per usufruire dei servizi l’utente dovrà ri-loggarsi. Body da specificare:

(37)

{

" to ken " : " xXyYzzzZ . . . " }

Con risposta, 200(OK):

{ ’ message ’ : " l o g o u t " }

/classify

E’ la richiesta utile per avere la predizione da parte del modello. Affinchè la richiesta vada a buon fine, l’utente deve essere loggato alla piattaforma. Body da specificare:

{

" img " : " b y t e A r r a y . . . " , " to ken " : " xXyYzzzZ . . . " }

Se l’immagine non fosse stata specificata, 205 (reimposta contenuto): { ’ message ’ : ’ Please s p e c i f y t h e image ’ }

Altrimenti, 200 (OK): { " s p e c i e " : " s ha rk " , " p r e c i s i o n e " : " x . y%" } /saveImage

L’utente, dopo aver scattato la foto, ha la necessità di salvare la foto nel proprio album. Il server riceve l’immagine e la salva nel database con u_id l’id dello user che vuole salvare la foto. Body da specificare:

{ " to ken " : " xxxyyxZzz " , " img " : " b y t e A r r a y " , " date " : " d a t e t i m e " , " t y p e " : " FishType " }

Se l’immagine non venisse specificata, ritornerebbe lo stesso messaggio di /classify. Nel caso in cui la data non fosse specificata:

{ ’ message ’ : ’ Please s p e c i f y t h e date ’ } In caso positivo:

(38)

" newpassword " : " newPassword " }

In caso positivo, 200 (OK):

{ ’ message ’ : " password m o d i f i e d " } Altrimenti, se la password da modificare non è corretta :

{ ’ message ’ : " password i s i n c o r r e c t " }

/loadImages

L’utente deve poter accedere al proprio album fotografico, visualizzando tutte le sue imma-gini catturate.

{ " t oke n " : " xXyYzzzZ . . . " }

E come risposta sarà ritornato l’array di immagini associate all’utente.

/delete

{

" to ken " : " xxxyyxZzz " , " date " : " d a t e t i m e " ,

}

L’immagine è identificata tramite la sua data di scatto. Come messaggio di risposta verra ritornato:

L’utente vuole poter eliminare immagini dal proprio album. { ’ message ’ : " image saved " }

NB: tutte le richieste che hanno bisogno del token per essere eseguite, hanno un unico

punto in cui è stata gestita la convalida del token: la funzione decoratrice @token_required

che in caso non lo convalidasse ritornebbe l’errore specificato al suo interno non permet-tendo il proseguimento della richiesta. Viene controllato che esso sia stato specificato al-l’interno del JSON e viene anche controllata la signature del token in modo da convalidare l’utente.

(39)

5.6

Funzioni di Encryption

Per aumentare la sicurezza dei dati sensibili nel codice e nei dati salvati su DB, sono state utilizzate delle funzioni di encryption. In particolare per questo bisogno è stata utilizzata la libreria ‘Fernet’.

key = F e r n e t . generate_key ( ) f = F e r n e t ( key )

to ken = f . e n c r y p t ( b "my deep dark s e c r e t " ) f . d e c r y p t ( t oke n ) # per d e c r i p t a r e

Lato server è stata criptata la password per accedere al database. Lato DB la password e il token associato ad ogni utente.

5.7

Unit test

Per lo sviluppo di unit test è stata utilizzata una libreria che non richiede installazione deno-minataunittest. Lato server sono state testate sostanzialmente le risposte di ogni singola

mappatura, verificando che il codice di risposta e il body siano come atteso.

• Creare un nuovo script allo stesso livello dello script da testare

• Importare la libreria

import u n i t t e s t

• Creare una classe che deriva dalla classe unittest.TestCase

class TestWebApp ( u n i t t e s t . TestCase ) :

• Definire test come funzioni che hanno un nome che inizia con test_

def test_GetPostMainPage ( s e l f ) :

Per eseguire i test digitare: py scriptTest.py Per risalire al code coverage è stata in-stallata una libreria coverage (pip install coverage) che ha il bisogno di eseguire i test con il comando

coverage run s c r i p t T e s t . py coverage r e p o r t

5.8

Librerie installate

(40)

Datetime

• CORS (affinchè ionic potesse comunicare con il server)

• Fernet

(41)

Capitolo 6

Client

L’utente deve poter comunicare con il server attraverso un’applicazione mobile. Grazie al-l’app l’utilizzatore è in grado di registrarsi alla piattaforma, loggarsi e utilizzare tutti i servizi messi a disposizone dal servente. Ha la possibilità di accedere a tutte le foto da lui scattate e classificate dal modello.

6.1

Ionic

Il framework utilizzato per lo sviluppo lato client è Ionic. Ionic framework è un toolkit di interfaccia utente open source per la creazione app mobili e desktop di alta qualità utilizzan-do tecnologie Web (HTML, CSS e JavaScript). Si concentra sull’interazione dell’interfaccia utente di un’app (controlli, interazioni, gesti, animazioni). Si integra perfettamente con altre librerie o framework come Angular, oppure può essere utilizzato in forma standalone. At-tualmente sta sviluppando il supporto per Vue e React. Punto di maggiore importanza è che con Ionic si creano app funzionanti su più piattaforme: IOS nativo, Android, Desktop e web come Progressive Web App. Vanta una vasta community pronta ad aiutare i futuri sviluppatori. Possiede un’interfaccia di linea di comando che include un server integrato, strumenti di creazione e debug (ecc..) che saranno argomentati nei capitoli successivi.

6.1.1

Installazione

Per l’installazione è stato utilizzatonpm che è il registro software più grande al mondo. Con

il comando (omettere sudo se si è sotto Windows) $ sudo npm i n s t a l l −g cordova

è possibile installare cordova che è il framework che permette di creare applicazioni mobili che non possono essere considerate né puramente native (il rendering è fatto con visualiz-zazioni web) né basate completamente sul web. Fornisce un layer intermedio tra funzioni native del dispositivo e ionic. Digitare poi (omettere sudo se si è sotto Windows)

(42)

Come detto ionic mette a disposizione un’interfaccia a linea di comando utile per creare un nuovo progetto, per debuggare le app che si stanno creando.

i o n i c s t a r t nomeApp <TIPO PROGETTO>

viene creato un progetto del tipo specificato, nel caso di FishClassifier <TIPO PROGETTO> = tabs.

Per eseguire l’app:

• su device connesso in modalità debug

i o n i c cordova run a n d r o i d device −−l i v e r e l o a d

• su browser(localhost:8100)

i o n i c s er ve −−l i v e r e l o a d

• su browser simulando il comportamento di IOS e Android i o n i c s er ve −l a b −−l i v e r e l o a d

6.2

Pagine

Lato applicazione l’utente interagisce con pagine html, stilate sotto regole CSS. Per la creazione di una pagina vuota digitare il comando:

i o n i c g e n e r a t e page

Dopo la creazione di un progetto in Ionic vengono già generate delle pagine in base al tipo di progetto creato. In automatico vengono generati tutti i file di configurazione per l’importazione di moduli e plugins (package.json, node_modules)

6.2.1

Tabs

L’app creata implementa una navigazione basata su tab. Una volta loggato, l’utente è in grado di accedere alla sua scheda utente, al tab adibito allo scatto dell’immagine da clas-sificare e al proprio album. Questa navigazione è gestita tramite il ’RouterModule’ utilizzato nella tabs page che funge da contenitore di tutti i tab (in questo caso 3). In base all’icona selezionata viene caricata la giusta pagina associata a quel tab. Come si evince, ogni pa-gina corrisponde ad un tab e tutti i tab sono gestiti da un punto di snodo che definisce la pagina da renderizzare e i compononenti da caricare.

(43)

Profile Tab In questa pagina l’utente è in grado di terminare la propria sessione da quel

dispositivo, cambiare la propria password e visualizzare sotto che account è loggato. Per visualizzare questo dato, in fase di login, è stato memorizzato l’username dell’utente.

Camera Tab Rappresenta il tab più significativo, include la funzionalità di scatto della foto

(44)

Il seguente diagramma di sequenza esprime a pieno tutte le interazioni del tab con gli altri componenti della piattaforma:

Album Tab Quando la pagina viene avviata, viene fatta una richiesta asincrona al server

(45)

[H]

L’utente ha la possibilità di selezionare una delle foto presenti nella galleria per poter avere maggiori dettagli riguardanti la foto. A questo scopo è stato utilizzatoion-modal che non è

(46)

[H]

6.2.2

Login

E’ la pagina renderizzata al primo avvio o nel caso in cui nessun altro utente è rimasto collegato tramite quel device.

(47)

Sono presenti due text_input contenuti in un form che controlla che entrambi i campi non siano nulli e in tal caso rende disponibile il click del tasto ‘LOGIN’. Tutto è gestito in angular lato HTML inserendo il parametro disabled nel tag del bottone:

< i o n−b u t t o n s i z e =" l a r g e " t y p e =" s u b m i t " [ d i s a b l e d ] = " form . i n v a l i d " expand =" b l o c k " > Login < / i o n−b u t t o n >

Viene creato un JSON con le informazioni appena immesse e viene fatta la richiesta del login al server che tornerà la corrispondente risposta. In caso l’utilizzatore non avesse un account ha la possibilità di crearne uno digitando sulla parola ‘register’ accedendo al form per la registrazione.

6.2.3

Register

L’utente entra a far parte della piattaforma compilando i tre campi mostrati in figura. Come il form per il login, il tasto ‘REGISTER’ è disponibile solo se i campi non sono null. Dopo aver compilato tutti i campi e aver cliccato sul bottone, viene controllato che i due campi ‘Password’ e ‘Password again’ coincidano e in caso positivo viene fatta la richiesta al server.

(48)

6.2.4

Change password

La pagina viene renderizzata nel momento in cui l’utente, sotto il tab ‘Profile’, digita ‘CHAN-GE PASSWORD’.

(49)

Affinchè la password sia cambiata l’utente deve specificare la vecchia password e inserirne una nuova ripetuta due volte (come nel caso della pagina di registrazione). Dopo aver clic-cato sul bottone ‘CHANGE’ verrà fatta una richiesta al server che modificherà la password e dopo averla criptata, la salverà nel database.

6.3

Async Function

E’ una funzione che esegue in modo asincrono utilizzando una Promise per ritornare il risultato. Il risultato di una funzione asincrona è un oggetto AyncFunction. E’ stato utile definire una funzione asincrona quando il client effettua le richieste al server, mostrando la barra di caricamento in modo da dare un feedback all’utente che qualcosa sta accadendo dietro le quinte.

A questo proposito è stato utilizzato il componente ‘LoadingController’ ed è stata defini-ta una funzione asincrona al cui interno veniva creato lo spinner con il messaggio ‘Plea-se wait. . . ’, per poi farlo visualizzare fino a quando la funzione di richiesta non terminava (questo chiamando la funzione ‘dismiss()’ del loadingController).

(50)

{ headers : myHeaders } ) . s u b s c r i b e ( response = >{ } , e r r o r = >{ } , ( ) => { l o a d i n g C o n t r o l l e r . d i s m i s s ( ) ; } ) ;

l’ultima riga va specificata solo nel caso in cui si volesse utilizzare lo spinner che rimane in attesa che la richiesta venga eseguita.

6.5

CameraPreview plugin

La scelta di utilizzo di questo plugin è stata solo a scopo estetico; infatti esiste un plugin più semplice da utilizzare denominato ‘Camera’. La differenza sta nel fatto che per scattare una foto con il metodo più semplice veniva utilizzato il layout della fotocamera predefinito del device, con CameraPreview invece è stato possibile wrappare in un elemento HTML la visualizzazione della fotocamera.

Installazione

I o n i c cordova p l u g i n add cordova−p l u g i n−camera−p r e v i e w npm i n s t a l l @ionic−n a t i v e / camera−p r e v i e w

Dopo di ciò verificare sotto ‘plugins’ che esso sia stato scaricato; verificare anche che nel package.json sia riportato il plugin con il link al repository github.

Utilizzo

Prima di tutto importare il componente, specificarlo nel costruttore della pagina dove la ca-mera deve essere utilizzata. Impostare i principali parametri tra cui il punto di partenza della visualizzazione in termini x e y (corrisponde all’angolo in alto a sinistra della visualizzazio-ne della fotocamera), altezza e larghezza, settare a false il previewDrag che indica che la renderizzazione della camera non è mobile all’interno della pagina. Chiamare la funzione ‘startCamera(parametriSpecificati)’ di CameraPreview all’interno della funzione ‘ionViewDi-dEnter()’ che nel ciclo di vita di una pagina indica il momento in cui la pagina sta per esse-re caricata. Nella funzione ‘ionViewWillLeave’ (quando la pagina sta per esseesse-re distrutta) chiamare il metodo ‘stopCamera()’.

(51)

6.6

Native Storage per la sessione

Lo storage nativo è stato utilizzato per salvare la ‘sessione’ dell’utente. In fase di login viene registrato l’username dell’utente che sta accedendo alla piattaforma, mentre in fase di logout i dati vengono resettati. Quando l’app verrà aperta ci sarà un controllo iniziale sull’username, se esso fosse vuoto l’app ridigerà l’utente alla pagina di login, altrimenti alle tabs pages.

6.7

Unit Test

Quando un’applicazione ’@ionic-angular’ è generata tramite CLI, è automaticamente impo-stata per eseguire unit-test.

Per verificare ciò è possibile eseguire il comando npm run t e s t

che apre il karma debugger che fornisce l’esito dei test scritti nei file .page.spec.ts .

Potenzialmente i moduli da testare sono le componenti ionic, i servizi. In questo progetto purtroppo non è stato svolto alcun test del genere.

(52)
(53)

Capitolo 7

Metodo AGILE

Per la pianificazione del progetto è stato utilizzato il metodo AGILE. Nato negli anni ’90 tale metodo si basa sull’interazione continua con gli stakeholder. Il progetto viene realizzato per fasi: Sprint.

Ad ogni Sprint corrisponde una nuova funzionalità e viene verificata la soddisfazione del cliente, al quale viene mostrato il lavoro svolto fino a quel punto.

In particolare è stato utilizzato il metodoScrum.

Scrum è un framework agile per la gestione del ciclo di sviluppo del software in modo ite-rativo ed incrementale. Gli Sprint che durano dalle 2 alle 4 settimane, si rivelano utili per coordinare il processo di sviluppo del prodotto con le esigenze del commitente/cliente. Ad inizio progetto è stato definito unProduct Backlog che è un documento che contiene la

lista di tutti i requisiti necessari per la realizzazione del progetto.

Ad ogni Sprint venivano scelti i requisiti utente con maggiore priorità che indicavano gli obiettivi da raggiungere per quell’iterazione.

La piattaforma utilizzata per svolgere queste pratiche organizzative si chiamaSCM.

Ad ogni sprint è assegnata una griglia in cui ogni colonna indica lo stato della feature descritta in orizzontale. Lo stato può essere ’New’, ’In progess’, ’Tested’ o ’Closed’.

(54)

Il progetto è stato suddiviso in 6 Sprint da 2 settimane ciascuno, in cui sono stati sviluppati incrementalmente e separatamente il modello di riconoscimento, il server e il client.

Sprint-001

Documentazione sui servizi esposti da Tensorflow, in cui è stato deciso di utilizzare Keras per la minore complessità di implementazione richiesta.

Sprint-002

Documentazione su progetti con Keras, studiando come un modello opera, i parametri da specificare in modo da migliorare la precisione del classificatore

Sprint-003

Confronto tra re-train di Inception-v3 e addestramento di un modello da zero.I risultati non erano tanto differenti e si è deciso di creare il modello. Sono stati necessari diversi addestramenti del modello combinando i diversi parametri per poi scegliere la soluzione migliore

Sprint-004

Il modello è stato poi affinato per poter essere utilizzato ad-hoc nel riconoscimen-to data in input un’immagine del pesce.Il numero di specie da riconoscere è stariconoscimen-to aumentato, richiedendo altro tempo di addestramento.

Sprint-005

E’ stato creato il server, includendo un sistema di autenticazione (JWT) e un database utile per la gestione degli utenti e delle immagini ad essi attribuiti (PostgreSQL). La comunicazione tra client e server è ora sicura utilizzando il protocollo ssl.

Sprint-006

E’ stato creata un’app Client che permettesse la comunicazione con il server. E’ stato utilizzato Ionic per lo sviluppo di quest’ultimo componente sviluppato. Sono

(55)

state create tutte le pagine necessarie affinchè l’applicazione potesse utilizzare tutti i servizi esposti dal server (login, logut, registrazione, classificazione dell’immagine, visualizzazione della galleria). Viene testato il server, controllando la robustezza del codice.

(56)
(57)

Capitolo 8

Conclusioni

Il progetto ha maturato le mie competenze nel settore, in particolare il suo sviluppo è sta-to fondamentale per comprendere i principali meccanismi utilizzati in una piattaforma che include diversi moduli.

8.1

Risultati

I risultati ottenuti sono accettabili e soddisfano i requisiti posti inizialmente.

8.2

Sviluppi futuri

La piattaforma richiede un ulteriore fase di addestramento del modello, richiedendo un ampio dataset a disposizione.

L’applicazione utente può essere migliorata aggiungendo features, così come il server. Un esempio può essere l’aggiunta della posizione GPS di dove il pesce è stato fotografato. Inoltre è consigliato migliorare la soluzione per la sincronizzazione delle immagini nella gal-leria utente. Attualmente per caricare le fotografie dei pesci fotografati viene effettuata una richiesta al server che torna un array di immagini che dopo vengono renderizzate nella schermata "Album". La modifica da apportare è quella di mappare le immagini tramite URL e effettuare N richieste, dove N è il numero di immagini per utente.

(58)
(59)

Allegati

Progetto_di_diploma_Converso Poster Poster_Converso Presentazione Presentazione_progetto_di_diploma.pdf Codice Modello(https://scm.ti-edu.ch/repogit/modello.git) Codice Server(https://scm.ti-edu.ch/repogit/server.git) Codice Client(https://scm.ti-edu.ch/repogit/client.git

(60)
(61)

Sitografia

[1] https://www.tensorflow.org/. [2] https://keras.io/models/sequential/. [3] https://keras.io/layers/convolutional/. [4] http://flask.palletsprojects.com/en/1.1.x/quickstart/a-minimal-application. [5] https://skymind.ai/wiki/convolutional-network. [6] https://towardsdatascience.com/image-classification-python-keras-tutorial-kaggle-challenge-45a6332a58b8. [7] https://cryptography.io/en/latest/fernet/. [8] https://www.mathworks.com/solutions/deep-learning/convolutional-neural-network.html.

Riferimenti

Outline

Documenti correlati

[30] Il primo comma prevede che siano fornite le informazioni seguenti: «a) l’identità e i dati di contatto del titolare del trattamento e, eventualmente, del suo

In order to identify the obstacles and strategies for the transition towards a circular economy, the study carried out an in-depth analysis, through interviews with

A recent research has revealed that in order to extrapolate the success obtained in culturing ro- dent follicles into larger species a multi-step dy- namic culture system is required

gli habitat e l’inquinamento delle acque quale causa di minaccia del benessere delle comunità ittiche autoctone, si intuisce come sia opportuna –oltre che necessa- ria– una

In particolare sono state applicate le metodologie dell’Indice dello Stato Ecologico delle Comunità Ittiche e dell’Indice Ittico, nelle loro più recenti versioni, sulla base

Nel corso di un lavoro di localizzazione, oltre che a trasporre il testo di partenza in un diverso sistema linguistico di arrivo, ci si può trovare di fronte alla necessità

Questo è un problema che merita attenzione, come tutti i problemi che riguardano gli infermieri e le altre figure professionali a cui viene data risposta attraverso leggi e