Buongiorno! Sono le 5:21, e benché sia sveglio da ben 20 minuti ho passato il tempo a guardare su Imagenet la lista dei dataset di annotation (file xml) per i corrispettivi dataset di immagini. E’ un file html lungo quanto schifoso, esteticamente parlando… sono solo link… coooomunque, passiamo alla sfida di oggi.
Sto anche pensando di compare una webcam, potrei riprendere i miei scleri nervosi… uhm.
Deep Photo Style Transfer
Oggi lavoriamo su una repository molto interessante: partendo da due immagini, una viene usata come stile di partenza per modificare l’altra. I potenziali risultati che si possono ottenere sono sbalorditivi ed emozionanti, ma ho idea che la strada sia in salita. Non demordiamo! Partiamo!
Ecco la prima cosa che mi ha fatto pensare:
“Given input and style images with semantic segmentation masks[…]”
Cosa devo dare in input? Per tutti i peli dell’alpaca cos’è una semantic segmentation mask? Che in italiano diventa una maschera di segmentazione semantica.
Se non erro deve essere l’applicazione di maschere di colore ai diversi elementi di un’immagine. Ma da qui, a crearne una per ogni immagine…
Aspeeetaaa
“Compute the matting Laplacian matrix using[…]“
Ma certo, the Laplacian matrix …

Siamo ignoranti. Appurato questo, facciamo le nostre ricerche.
Frena, ho visto che alcuni script sono scritti in lua, è un linguaggio di programmazione che praticamente non conosco, lo usai qualche hanno fa per un bot di telegram che girava su un server remoto, ma se ricordo bene è molto semplice.
E’ tempo di ricerche

Ok. Facciamo un po’ di chiarezza.
La repository si basa, come scrito in pompa magna su Torch che è un framework sviluppato per il machine learning basato su Lua. Questo spiega il motivo per cui abbiamo visto poco fa gli script lua.
Ora però, esiste questo boy che ha implementato il sistema dietro il deep photo style transfer in tensorflow e dato che abbiamo, o dovremmo avere, già tutto pronto direi che passiamo a lui. Magari non otteniamo gli stessi risultati, ma proviamo.

Il boy… è Siraj Raval. Questo invece il motivo per cui non me ne sono accorto prima. Avevo aperto il link, poi lo avevo chiuso e nel frattempo ero finito sulla repository di GitHub: ho scambiato le persone. Poco male. Abbiamo due risorse.
Non vorrei essere troppo positivo, ma ho idea che sarà una cosa veloce.
Scarico la repository.
Questo sistema usa una rete convoluzionale, che tradotto in soldoni: basandosi sulla struttura della corteccia visiva animale unisce i neuroni artificiali per creare un moello analogo.
La rete usata è la VGG-19

E questa è la sua struttura. Mentre noi abbiamo un neurone.
Ne abbiamo di strada da fare. Bando alle ciance, scarichiamo anche il VGG-19.
Copiamolo nella directory corretta et voilà.
Iniziamo a dare i primi comandi e vedere i primi errori.
Ora, io non ho installato tutte le dipendendze perché aspetto di vedere se causano problemi oppure no. Una in particolare mi lascia pensare… la PyCUDA. Se dovesse causare problemi con le librerie già presenti…
Ho finitio di dire cacchettine di struzzo e ho installato pycuda.

Ok, ora ho capito il discorso della segmentazione. In pratica la repository, e a questo punto suppongo anche la prima che abbiamo visto, contiene al suo interno una cartella di immagini con diversi stili. Quindi, fino a quando non realizzeremo uno script che partendo da un’immagine generi la maschera di segmentazione semantica, siamo “limitati” ai 60 stili precaricati, già dotati di maschera.
Continuo a non capire, dal momento che anche l’immagine su cui si vuole applicare lo stile pare debba essere segmentata.
Esatto, è così. Come appare anche evidente dal fatto che l’autore specifica l’assenza dei file di script per ottenere la segmentazione e afferma di aver preso le immagini dalla repository di partenza, la prima che abbiamo visto.
Ladro.

Le risorse che non consuma…
Fuori di testa!
Non è ancora finito… per fare una sola immagine impiega 4 minuti… pensa applicarlo ad un video… 25 immagini per ogni secondo... ma ciao proprio. Perché deve fare 2000 interazioni…
Ore 6:58.
Sono andato a farmi una bella colazione. Nel frattempo ho lasciato il computer lavorare. Quando apro la porta della stanza, oltre i 35 gradi di caldo tropicale causa stress intenso della GPU mi siedo davanti al monitor che ormai è abituato a stare sopra un forno, leggo la shell…

Ora. La notazione x / 2000 generalemente nei programmi indica a sinistra la quantità a cui sei arrivato di qualcosa e a destra la quanità finale… ma zio impanato perché segna 3560. E’ come comprare un’auto che sul libretto indica un serbatoio da 50L. Allora vai al benzinaio, fai il pieno e il contatore sale. Poi continua a salire, poi sale ancora. Ti giri un attimo, e hai prelevato 250L di benzina… Ma zio impanato fritto, se il serbatoio era da 50?!
Ah certo, in più scopri che il serbatoio manco c’era eh sì!. Qalcuno ha visto la foto modificata? Nessuno? Nemmeno io. Quindi abbiamo 10 gradi in più in stanza, consumato un po’ di elettricità e parecchio tempo ma nessun risultato decente. Fantastico.
Cosa fai quando qualcosa non funziona? Lo smonti.


Prima di proseguire oltre… Devi sapere che la repository contiene diverse cartelle, e io ero dentro quella chiamata “examples“, e da bravo scemo mi aspettavo che i risultati fossero lì dentro… Quindi ho pensato “bene, non c’è manco l’impanatura dello zio, figuriamoci se c’è l’olio per friggerlo” e volendo aprire con Atom gli script per capire cosa non andasse sono tornato alla radice della repository e…
Bellissimo…
Il risultato finale è… wow.
E non ho scritto una riga di codice, perché altrimenti a quest’ora mi sentirei… non lo so non ho parole per descriverlo, andrebbe provato e basta.

Ora ho capito il motivo per cui la licenza non è a fini commerciali…
Ho passato un po’ di tempo a diventare confidente con alcuni termini tecnici, e in particolare ho capito cosa sia una matrice laplaciana, devo ancora capire in che modo questa torna utile nel nostro esempio. Sicuramente una lettura alla documentazione ufficiale sarà di cospicuo aiuto.
Prima di creare la guida, cerchiamo in rete lo script per estrarre la maschera di segmentazione semantica.
Nel frattempo, l’UniCT ha una risorsa online utile per futuri approfondimenti.
E quasi un’ora che cerco online informazioni sulla segmentazione ma credo sia qualcosa di nicchia. Ho trovato una suite, ma devo capire quali modelli posso usare. Invece di cercare, agiamo con il trial end error method.

Ci siamo. Questa repository dovrebbe fare al caso nostro.
Allora, scaricato il file, attivato l’ambiente, avviato lo script e abbiamo un problema di memoria. Allochiamone meno:
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.744)sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
And we have lift off!
Abbiamo il sistema per segmentare un’immagine, anche se non sappiamo bene quanto efficace sia. Ora scarichiamo il secondo modello e vediamo che diferenza di risultati c’è.
Immagine Segmentazione
Ora non ci resta che provare con qualche immagine nostra e scrivere la guida!
Alla prossima.
Un caldo abbraccio, Andrea.