[python] Semplice esercizio per riconoscere immagini di frutti con TensorFlow (machine learning)

Vogliamo realizzare un semplice programma in Python che sia in grado di riconoscere, utilizzando TensorFlow e machine learning, delle immagini di frutti.

Questo esercizio riprende i medesimi concetti già visti in: [python] Semplice esercizio su TensorFlow e il riconoscimento delle immagini nel gioco del Tris (Machine Learning)

Dato il seguente set di immagini (qui unite in una singola), vogliamo addestrare il programma a riuscire a riconoscere correttamente i frutti rappresentati:

Per farlo addestreremo il programma con altre immagini di training, suddivise rispettivamente in mele (che forse assomigliano più a dei pomodori), pere e banane:

 

 

 

 

 

Il risultato che vogliamo ottenere analizzando la prima immagine sarà qualcosa del genere (abbiamo tagliato l’immagine in tutte le sottoparti):

I tre numeri rappresentano la percentuale di probabilità per cui l’immagine sia, rispettivamente, una mela, una pera o una banana. Questo significa che la prima immagine è al 100% di probabilità una pera, mentre la seconda una banana ecc.

Il progetto si sviluppa in Python 3.7. Prima di procedere assicuriamoci di aver installato tutte le librerie necessarie, in particolare:

A questo punto prepariamo le immagini per il training ed il test. Attraverso le immagini di training alleneremo il nostro algoritmo, mentre useremo quelle per il test per verificare l’efficacia. Sottolineo ancora una volta come questo sia un esempio semplificato al massimo, utilizzando immagini semplici per non dover produrre una grande mole di dati sia per il training che per il test.

Per preparare le immagini dobbiamo tagliare i quattro file precedentemente preparati. A tale scopo creiamo una classe per elaborare le immagini nel modo seguente (nei commenti c’è la descrizione delle singole operazioni):

Per elaborare i due gruppi di immagini ci sarà sufficiente chiamare:

A questo punto creiamo una classe per elaborare questa base dati, nel modo seguente:

Fatto tutto questo possiamo anzitutto costruire il nostro modello, che andremo a salvare, nella stessa cartella dell’eseguibile come modello_frutta.

Per creare il modello anzitutto preleviamo le immagini con:

Costruiamo poi il nostro modello:

I tre layer servono rispettivamente per:

  1. keras.layers.Flatten(input_shape=(100,100,3)) ci permette di ridurre ad una dimensione la matrice tridimensionale delle immagini (100 righe x 100 colonne x 3 byte di colore) contenente 30.000 byte. Per farlo dobbiamo ricordarci lo shape dei dati passati in input, che provengono da una lista, contenente a sua volte una lista tridimensionale.
  2. keras.layers.Dense(128, activation="relu") applica l’algoritmo relu ai dati ottenuti dal primo layer, su 128 nodi (il numero è arbitrario, scelto per via principalmente sperimentale)
  3. keras.layers.Dense(3, activation="softmax") applichiamo l’algoritmo softmax per ridurre tutte le informazioni a 3 nodi, rappresentati i 3 dati di output che vogliamo ottenere.

Aggiungo una nota per comprendere meglio il passaggio dei layer intermedi. Il primo layer è necessario per ridurre i dati in input ad una forma univoca, mentre l’ultimo layer serve a portare in output i dati che passiamo come “descrizione”, ovvero output conosciuto, durante il training. I layer intermedi invece possono essere molteplici, e servono per manipolare i diversi aspetti dell’informazione, tentando di ridurla ad una schematizzazione ricorrente. Per capire meglio questo processo immaginiamo di voler interpretare un’immagine (non succede la medesima cosa, ma l’esempio descrive bene il concetto generale).

Se avessimo un immagine come questa di seguito, avremmo a che fare con un’enorme quantità di dettagli diversi da analizzare. Essendo l’immagine grande 1200 x 761 pixel, potremmo dire di aver bisogno di 1200×761 = 913.200 nodi per interpretare ogni informazione singolarmente, quindi potremmo decidere di utilizzare un layer con 913.200 nodi (o neuroni). Questo vorrebbe dire che diamo importanza ad OGNI singolo nodo e quindi ad OGNI singolo dettaglio dell’informazione. Laddove volessimo confrontare immagini diverse sarebbe molto complesso cercare di trovare un’affinità tra i singoli nodi e quindi un percorso che riconduca al medesimo output desiderato.

Albania Sud | Vagabondo

Dello stesso posto potremmo avere ad esempio la seguente immagine:

Turismo dentale Albania | EliteDental

Le due immagini risulterebbero, per il computer, prese tali e quali, fondamentalmente diverse. Adesso proviamo a ridurre il dettaglio dei pixel, nel modo seguente:

Adesso possiamo identificare, nelle immagini divese, zone analoghe associabili per forma e colore tra di loro (nonostante le differenze ancora esistenti). In questo caso abbiamo ridotto le immagini in quadrati da 36×36 pixel ciascuno, quindi in totale abbiamo ridotto il tutto a circa 700 nodi. Ovviamente si è ridotta la complessità e di conseguenza il livello di dettaglio. Potremo apprezzare meno dettagli, ma confrontare meglio i macro-elementi presenti in entrambe le immagini.

Detto tutto questo compiliamo il nostro modello:

E infine compiliamolo e salviamolo:

Per usare il modello salvato lo possiamo caricare usando:

A questo punto carichiamo le immagini di TEST e mettiamo a prova il nostro modello:

Adesso facciamo prevedere al modello i risultati:

Infine stampiamoli a video per ottenere il risultato iniziale:

Riporto anche tutto il codice insieme:

Qui il progetto con le immagini scaricabile in formato zip.

Vedi articolo

[python] Recuperare i messaggi cancellati definitivamente da un file *.pst di Outlook

Outlook salva tutto il contenuto dell’account di posta dentro ad un file *.pst che viene trattato similmente ad uno spazio sul disco. Questo significa che quando un messaggio viene cancellato definitivamente (per esempio svuotando il cestino oppure cancellandolo con SHFIT+CANC) in realtà non viene rimosso definitivamente dal file, ma ne rimane traccia finché un nuovo messaggio non andrà a sovrascriverlo. Questa non è una spiegazione perfettamente accurata, ma è quanto ci serve sapere allo scopo.

Per recuperare un messaggio cancellato definitivamente è anzitutto importante non scaricare o inviare nuovi messaggi, non fare cioè alcuna operazione che potrebbe modificare il file *.pst.

Detto questo possiamo tentare di recuperare i dati modificando alcuni byte del file *.pst e utilizzando il programma Scanpst.exe fornito assieme ad Office. Dalla versione Microsoft Office 2016 il programma è eseguibile anche tramite linea di comando.

Vediamo quindi come creare un programma in python che ci permetta di effettuare le due operazioni recuperando quindi i messaggi.

Prima di procedere creiamo una copia del file *.pst per non provocare altri danni.

Quello che dobbiamo fare ora è modificare, mettendoli per esempio a 0, i primi 13 byte a partire dalla 7^ posizione nel file *.pst in questione. Questo farà sì che Scanpst.exe identifichi il file come corrotto e cerchi di recuperare i messaggi perduti. Usando un editor esadecimale, tipo Hex Edit, dovremmo vedere una situazione come la seguente.

Quelli che vogliamo mettere a 0 sono i byte evidenziati. Io lo farò usando python. Creiamo un vettore di byte a zero nel modo seguente:

Questo produrrà un vettore di byte che possiamo visualizzare con print( byte_vuoti )

Scriviamo il pezzo di codice necessario per modificare il file *.pst

Con fp.seek(7) ci posizioniamo sull’ottavo byte, e poi scriviamo i 13 byte a 0 dalla posizione acquisita.

Adesso passiamo il file a Scanpst.exe, potremmo farlo anche a mano, ma nel mio esempio lo farò tramite linea di comando.

Modifichiamo il codice soprastante nel modo seguente:

Per maggiori dettagli sui parametri da passare a Scanpst.exe rimando alla pagina ufficiale sul sito della Microsoft: Lo strumento Manutenzione Posta in arrivo (Scanpst.exe) può eseguire controlli multipli in Outlook 2016

Con os.path.dirname(os.path.realpath(__file__)) prendiamo la posizione del programma in python, laddove io suppongo che il file Outlook si trovi nella medesima cartella del programma. Inutile dire che file_pst = dir_path + "\\Outlook.pst" dipende dalla posizione del file *.pst che potremmo passare anche con il percorso diretto.

Con la riga scanpst = "C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\SCANPST.EXE" prendiamo la posizione del file Scanpst.exe che nel mio caso ha quel percorso. Anche questo dipende dalla nostra specifica installazione di Office. Ricordiamoci che questo procedimento è valido solo per le versioni di Office 2016 e successive.

Infine con output = os.popen(cmd).read() mettiamo il programma in attesa finché non verrà completata l’esecuzione del comando. (verrà scritto Fatto!)

Alla fine, se tutto è andato bene, dovremmo vedere qualcosa di questo genere nella cartella del file:

Per visualizzare di nuovo il contenuto del file *.pst è sufficiente collegarlo tra i File dati di Outlook.

Vedi articolo