Acquisire testo da immagini con Python – Parte 2 – Tesseract e il primo test di acquisizione

Nel precedente post al fine di provare ad acquisire e aggregare dati provenienti da schermate di un video gioco anni novanta abbiamo chiesto a ChatGPT di darci una mano nel compito essendo neofiti totali. La scorsa volta ci siamo fermati all’installazione di Python, ora passiamo a Tesseract.

Tesseract

Se proviamo a far girare il codice che ci ha fornito ChatGPT scopriamo che manca un prerequisito che è Tesseract. Ma cos’è esattamente?

Ecco la risposta sempre di ChatGPT

La risposta di ChatGPT

Bene, Tesseract è un OCR ed è utilizzato per estrarre testi dalle immagini: quello che mi serve. E’ Open-Source, supporta il riconoscimento in varie lingue ed è molto accurato se correttamente “allenato” (interessante). Può essere facilmente utilizzato attraverso API e nello sopecifico per sessere tuilizzato in Python necessita della libra “pytesseract”. Direi che è esattamente quello che mi serve. Per installare Tesseract basta un semplice comando con brew [1]

brew install tesseract

Inifine come suggerito da ChatGPT installo anche il wrapper per Python.

pip install pytesseract

A questo punto possiamo cominciare a lavorare sul codice Python per capire come adattarlo e ricondurlo a quelle che sono le mie necessità.

Primo ciclo di codice

Apriamo Visual Studio Code e creiamo un file vuoto Test.py e copiamo il codice suggerito nel post precedente quindi lanciamo l’esecuzione dal menu Run > Start Debugging. Questo è il risultato:

Primo lancio

L’esecuzione va in errore e la modalità debug di Visual Studio Code ci aiuta evidenziando dove sta il problema: certo devo fornire un path corretto dove prelevare gli screenshots. Al netto di questo errore comunque il setup sembra corretto possiamo quindi dedicarci alla parte più divertene: vale a dire scrivere il codice. Anzitutto faccio un po’ di pulizia: rimuovo la parte che fa la categorizzazione perchè al momento non so ancora come poterla implementare e lo stesso faccio con la funzione che scrive il csv. Infine fornisco il path dove ho già preparato alcuni screenshots da cui estrarre il testo che mi serve. Il main dopo questo restyling è molto minimale:

# Main function to execute the workflow
def main():
    # Path to the folder containing screenshots
    screenshot_folder = ""/Users/xxxx/ScreenCapture""

    # Extract data from screenshots and rename files
    extract_data_and_rename(screenshot_folder)

Infine mi dedico alla funzione principale extract_data_and_rename che chiaramente itera i files nella cartella e tramite pytesseract estrae il testo dell’immagine. Al momento però mi limito a fare un print del dato estratto:

# Function to extract data from screenshots and rename files
def extract_data_and_rename(screenshot_folder):
    for file in os.listdir(screenshot_folder):
        if file.endswith(".png"):
            img_path = os.path.join(screenshot_folder, file)
            img = cv2.imread(img_path)
            # Implement OCR to extract data from the image
            extracted_data = pytesseract.image_to_string(img)
            # Extract relevant information from the data
            print(extracted_data)

Ok ci siamo se lo lanciamo teoricamente dovrebbe iterare tutti i files png presenti nella cartella e scrivere il contenuto estratto da ognuno di essi a schermo. Per questa prima prova uso una sola immagine:

Immagine sorgente

e questo è ciò che il sistema è stato in grado di interpretare:

Testi estratta dallo screenshot

Beh, diciamo che come primo test è già qualcosa però è evidente che alcuni testi sono stati correttamente interpretati mentre altri vanno rivisti. C’è parecchio da lavorare!

[1] https://pyimagesearch.com/2021/08/16/installing-tesseract-pytesseract-and-python-ocr-packages-on-your-system/

Acquisire testo da immagini con Python – Parte 1 – Cominciamo dalle basi

Qualche giorno fa in questo post [1] parlavo dei temi relativi all’AI e le sue differenze con la pura automazione. Come esempio pratico vorrei provare ad acquisire in automatico i dati provenienti da alcune immagini e convogliare queste informazioni in un excel. Dovete sapere che io sono un grande amante dei giochi degli anni ottanta e novanta. E voi direte che centra questo? Uno dei giochi sul quale ho perso letteralmente le notti quando ero poco più che un teenager era Championship Manager (Scudetto nell’edizione italiana). E’ stato il primo gioco a fornire una simulazione di ottimo livello del manager calcistico. Sono passati gli anni, sarà l’età avanzata, sarà del sano romanticismo, ma ancora questo gioco riesce a toccare corde cui i giochi strafighi di oggi difficilmente riescono a sfiorare. Se non lo conoscete vi invito a fare un giro su questo sito [2] dove potete addirittura scaricare il gioco (nella versione 97/98) e con dosbox [3] un simulatore di DOS potete persino giocarci. Ebbene una delle cose che ho sempre desiderato fare è avere uno scarico dei dati di giocatori e partite per poterli incrociare avere delle statistiche da cui possibilmente evincere trends ed informazioni utili a schierare le formazioni migliori.

Una schermata di esempio è quella delle skills di un singolo calciatore in cui ci sono info anagrafiche e capacità tecniche

Scheda calciatore

Nella fattispecie mi piacerebbe quindi avere in un unico excel le skills per colonna e i giocatori per riga magari indicando anche la data in cui questi dati sono stati raccolti con l’idea di poter monitorare un giocatore anche in giorni diversi nel caso le sue skills migliorino o peggiorino. Detto questo non ho la minima idea di come procedere, quindi chiedo a ChatGPT se mi può dare una mano:

Definizione del requisito

Chiedo scusa per l’inglese maccheronico, ma penso si capisca abbastanza bene. Ed ecco la risposta:

Prima parte della risposta

Bene, diciamo che già la lista delle attività pone sul tavolo alcuni strumenti come Python, OpenCV… In più mi porta cnhe un esempio di codice Python da utilizzare:

import os
import cv2
import pytesseract
import csv
from datetime import datetime

# Function to categorize screenshots based on format
def categorize_screenshots(screenshot_folder):
    # Implement your logic to categorize screenshots
    pass

# Function to extract data from screenshots and rename files
def extract_data_and_rename(screenshot_folder):
    for file in os.listdir(screenshot_folder):
        if file.endswith(".png"):
            img_path = os.path.join(screenshot_folder, file)
            img = cv2.imread(img_path)
            # Implement OCR to extract data from the image
            extracted_data = pytesseract.image_to_string(img)
            # Extract relevant information from the data
            # Rename the file using extracted data and current date
            new_filename = f"{extracted_data}_{datetime.now().strftime('%Y-%m-%d')}.png"
            os.rename(img_path, os.path.join(screenshot_folder, new_filename))

# Function to fill CSV files with data from screenshots
def fill_csv_files(screenshot_folder, csv_folder):
    for file in os.listdir(screenshot_folder):
        if file.endswith(".png"):
            img_path = os.path.join(screenshot_folder, file)
            img = cv2.imread(img_path)
            extracted_data = pytesseract.image_to_string(img)
            # Write extracted data to CSV file
            csv_filename = file.replace(".png", ".csv")
            with open(os.path.join(csv_folder, csv_filename), "w", newline="") as csvfile:
                csv_writer = csv.writer(csvfile)
                # Write data to CSV file
                csv_writer.writerow(extracted_data.split("\n"))

# Main function to execute the workflow
def main():
    # Path to the folder containing screenshots
    screenshot_folder = "path/to/screenshots"
    # Path to the folder where CSV files will be stored
    csv_folder = "path/to/csv_files"

    # Categorize screenshots
    categorize_screenshots(screenshot_folder)

    # Extract data from screenshots and rename files
    extract_data_and_rename(screenshot_folder)

    # Fill CSV files with data from screenshots
    fill_csv_files(screenshot_folder, csv_folder)

if __name__ == "__main__":
    main()

Fantastico: non avevo idea da dove cominicare e ChatGPT mi ha dato delle indicazioni preziose per cominiciare ad approfondire i temi.

Python

Non conosco questo linguaggio se non per sentito dire: non ho mai scritto mezza riga di codice, ma mi sembra di poter dire, dall’esempio che riporta ChatGPT, non sia poi così complesso. Leggendo su Wikipedia [4] tra l’altro scopro che deve il nome ai Monthy Python, già questa la dice lunga. Installarlo non è complesso basta seguire gli step indicati nelle varie guide online (tipo questa [5]). Anzitutto verifico che non sia già presente con questo comando a terminale:

python --version

Nel mio caso il risultato è quello che vedete (io ho installato la versione 3)

Bash

Nel caso non lo abbiate installato potete seguire la guida utilizzando brew

brew install python

Ora che Python è finalmente installato possiamo aprire Visual Studio code e utilizzando il codice che ChatGPT ci ha fornito creiamo un file .py di test da eseguire.

Nel prossimo post vedremo le librerie da utilizzare in Python così come ce le ha suggerite ChatGPT.

[1] https://www.beren.it/2024/02/08/automazione-o-intelligenza-artificale/

[2] https://www.fmscout.com/a-cm9798-v2-project.html

[3] https://www.dosbox.com

[4] https://it.wikipedia.org/wiki/Python

[5] https://www.jcchouinard.com/install-python-on-macos/

Configurare GitHub in una React App con Visual Studio Code

Per chi lavora al codice è importante poter aver repository di codice che consenta principalmente due cose:

  • La gestione del codice in maniera concorrente: tipicamente più sviluppatori possono aver necessità di lavorare sugli stessi files, senza ostacolarsi e senza che l’uno “distrugga” quanto fa l’altro
  • La gestione delle versioni: avere la possibilità di tenere più versioni dello stesso file basate sul quando il file stesso è stato “salvato” nel repository consentendo rapidamente di individuare possibile problemi introdotti ad esempio con un cambiamento sull’ultima versione e poter riprisitnare una versione qualsiasi precedentemente salvata.

In questo post utilizzeremo come repository GitHub, che è del tutto free e consente agli utenti registrati di avere un repository on cloud sempre disponibile ed anche condivisibile. Assumendo di avere già un account creiamo online un nuovo repository (il nome lo potete scegliere a piacere) evitando di inizializzarlo dato che partiamo da una app react creata localmente (date un’occhiata a questo post [1] se non sapete come farne una).

GitHub – Create Repository

Una volta cliccato su Create Repository viene mostrata una pagina di configurazione in cui sono indicati i comandi da lanciare in console per creare e pushare il codice sul repostory appena creato. Basta copiare, incollare nel terminale e cliccare su invio.

GitHub – Repository Commands

A questo punto nella schermata di Visual Studio Code nel tab del versioning appaiono tutti i files della soluzioni che devono essere aggiunti.

Repository files list

I files hanno ora tutti una U sulla destra ma che significa esattamente?

  • U (Untracked): sono files aggiunti al progetto ma non ancora commitatti e nemmeno aggiunti all astaging area
  • M (Modified): un file presente nel repository e modificato
  • A (Added): un file aggiunto alla staging area
  • D (deleted): un file tracciato nel repository e cancellato localmente
  • C (Conflict): un file che ha un conflitto di versione

Quando parliamo di staging area definiamo quei files che vanno a formare un commit e che non sono ancora presenti nel repository.

Ora non resta che scrivere un commento nel box e cliccare commit. Quindi premere push per sincronizzare il tutto. Il risultato è che ora in GitHub nel repository indicato ho tutti i files del mio progetto locale.

Respository load in GitHub

Un occhio attento però noterà che non tutti i files che sono presenti nella cartella locale del progetto sono stati importati. Ad esempio build o node_modules non sono presenti. In realtà ciò è corretto ed il perchè è definito all’interno del file .gitignore posso definire quali file ignorare perchè superflui. Nella fattispecie build contiene la pubblicazione del sito mentre node_module ritorna i pacchetti utilizzati per la build.

[1] https://www.beren.it/2024/01/19/la-mia-prima-react-app/

La mia prima React App

React è una libreria Javascript tra le più utilizzate nell’implementazione di interfacce web [1]. E’ molto utilizzata per chi lavora con le Sigle Page Application in cui buona sostanza a differenza delle standard web application il DOM viene riscritto per intero ad ogni interazione lasciando al browser l’onere di ridisegnarla in base alla navigazione utente. E’ una modalità che ben si sposa con il concetto di Headless e di architettura composable.

Per prima cosa bisogna installare node.js sulla macchina dove si prevede di sviluppare l’applicazione. A questo punto possiamo utilizzare un comando specifico da terminale per creare l’app: create-react-app. Questo comando lancia la creazione dell’applicazione nella folder corrente del terminale quindi fate attenzione a quando lanciate il comando.

npx create-react-app hello
Crazione della React App

Al termine di un processo che può durare alcuni minuti questo comando genererà la struttura di files che vanno a comporre l’applicazione e che è ben descritta qui [2].

Abbiamo creato il template di app, ora ci serve aprire il tutto in editor di testo dove ci venga facile fare modifiche e lavorare sui files. Ci sono decine di editor ma quello che vi consiglio è Visual Studio Code (lo trovate qui [3]), è free, è leggero ed ha un sacco di estensioni utili. Vale la pena porre attenzione sui due files principali:

Entry Point

Questi files devono essere sempre presenti perchè sono sorgente da cui parte tutto. Index.html in particolare ha in div con id=”root” dal quale parte tutto: è all’interno di questo div che verranno generati di volta in volta i componenti da visualizzare nella pagina.

Index.html

Questo compito verrà svolto da index.js che come vedete sotto ricercherà quel did e lo sostituirà con qualcosaltro che la soluzione definisce, in questo caso <App /> che non è nientaltro che tutto ciò che si trova nel file App.js prsente sempre nella cartella src.

index.js

A questo punto per vedere l’app in azione non ci resta che aprire un nuovo Terminal dal menu di Visual Studio Code ed eseguire il comando:

npm start

Ed eccoci quà l’applicazione demo funziona:

Quando invece dovete pubblicare l’applicazione il comando da utilizzare è leggermente differente: npm run build.

npm run build

Questo genererà una cartella build nella root del progetto.

Build folder

Nella lista dei files se ne trovano due che hanno come nome package.json e package-lock.json. Il nome è molto simile e potrebbe trarre in inganno sul loro significato. Package.json definisce i package e le relative versioni da utilizzare nel progetto. Questo significa che lanciando il comando npm install il sistema in base alle versioni installate sulla macchina definirà quale combinazione di package utilizzare e creerà il file package-lock che a quel punto contiene esattamente tutti i package utilizzati sulla macchina.

[1] https://react.dev/

[2] https://create-react-app.dev/docs/folder-structure

[3] https://code.visualstudio.com/download