Riconoscimento ottico dei caratteri (OCR)
Leggere il testo da un'immagine o da un file PDF tramite OCR con Google Apps Script
Con Google Apps Script è possibile estrarre il testo da un'immagine (JPG, PNG, GIF) o da un file PDF per salvarlo all'interno di un nuovo documento (Google Docs) in Google Drive.
Inutile spiegare gli enormi vantaggi di questa opportunità, basti pensare a quanti documenti scansionati abbiamo, o cartacei da scansionare per portare in formato digitale, e quanti di essi sono immagini statiche dove il testo non è selezionabile.
Con poche righe di codice in Apps Script abbiamo la possibilità di estrarre il testo in essi contenuto per poterlo utilizzare e rielaborare a proprio piacimento.
Lo script mostrato di seguito si avvale delle API di Google Drive (maggiori dettagli nella documentazione ufficiale, REST v2), in particolare quella per sfruttarne le potenzialità del relativo motore OCR (riconoscimento ottico dei caratteri), al fine di estrarre il testo contenuto all'interno di un'immagine in formato JPG che risiede sul web (la funzione accetta in ingresso un parametro definito dall'url del file che si intende processare) ed inserirlo in un Google Docs pronto per essere utilizzato:
function extractTextFromImageOrPDF(url) {
// Accede alla risorsa web indicata e ne recupera i dati
var blob = UrlFetchApp.fetch(url).getBlob();
// Recupera i dettagli del file: il suo nome ed il tipo
var resource = {
title: blob.getName(),
mimeType: blob.getContentType()
};
// Crea un file su Drive con le informazioni passate e parametri per abilitare l'ocr e relativa lingua
// Per attivare questa funzionalità è necessario abilitare l'Advanced Drive API Service
var file = Drive.Files.insert(resource, blob, {ocr: true, ocrLanguage: "it"});
// Recupera l'istanza del doc appena creato
var doc = DocumentApp.openById(file.id);
// Recupera il testo, interpretato dall'OCR, dal doc
var text = doc.getBody().getText();
return text;
}
function main() {
// Inserisci l'url dell'immagine o del pdf dal quale vuoi estrarre il testo
var url = 'http://media.bigbossweb.com/corporates/.../dante_inferno_lettura_ocr_con_gas.jpg';
// Richiama la funziona per il riconoscimento ottico dei caratteri (OCR)
var text = extractTextFromImageOrPDF(url);
// Il testo è visualizzabile nel log, oltre che su Drive nel file appena creato
Logger.log(text);
}
L'utilizzo dello script di cui sopra è molto semplice, basterà sostituire l'url del file con quello di interesse (il file può risiedere anche su Drive), modificare il parametro ocrLanguage in base alla lingua del documento ed avviare la funzione main().
Nota che, utilizzando le API di Drive è necessario abilitare l'uso delle API dei Servizi Avanzati di Google nel progetto in questione (nel caso dello script oggetto del presente tutorial l'abilitazione deve essere effettuata per le Drive API).
Di seguito trovate un esempio del risultato per mostrare le potenzialità dello script appena proposto.
L'immagine utilizzata, presente in rete, è la seguente, Fig. 1:
Eseguendo lo script dall'editor di Apps Script ed aprendo la finestra di log dal menu 'Visualizza -> Log' è subito possibile notare come il testo presente all'interno dell'immagine sia stato riconosciuto ed estratto, Fig. 2:
Lo stesso contenuto è stato inserito in un Google Docs, presente su Drive con lo stesso nome del file originale, pronto per essere utilizzato, Fig. 3:
Ci sono alcuni suggerimenti da tenere in considerazione al fine di ottenere un risultato ottimale, come ad esempio la dimensione del font che non deve essere inferiore ai 10px, la dimensione del file che non deve superare i 2MB oppure l'orientamento del documento da prevedere prima della sua elaborazione. Per la lista completa dei suggerimenti rimando alla pagina ufficiale di supporto della guida di Google Drive relativa alla conversione di pdf e file fotografici in testo.
trovo molto interresanti tutti i tuoi tutorial posso chiederti alla fine di automattizare i processi se io avessi piu' file in una cartella di drive posso dare in pasto queta cartella al programma tipo con l'istruzione
es. var url = DriveApp.getFoldersByName(name).searchFiles(); e poi far seguire un ciclo (for x) in modo da fargli passare ogni file ed eventualmente se ne viene aggiunto uno di nuovo? tu cosa ne pensi ?? GRAZIE
Ciao Mauro,
il metodo searchFiles così come quello searchFolders, si aspettano come parametro un criterio di ricerca (come da documentazione ufficiale: https://developers.google.com/apps-script/reference/drive/drive-app#searchfilesparams).
Nel modo in cui lo hai impostato credo che ti possa essere restituito l'errore 'Impossibile trovare il metodo searchFiles()'.
Di seguito un esempio funzionante per la ricerca in Drive di tutte le cartelle che contengono nel nome la stringa definita:
Personalmente utilizzerei i classici metodi getFiles() e getFolder() per il recupero di tutti i file all'interno di una cartella.
Un esempio può essere il seguente:
Nel caso tu abbia bisogno di riconoscere i file nuovi da quelli già processati devi inventarti qualcosa come ad esempio rinominare quelli già gestiti (e quindi escluderli all'interno del ciclo successivo) oppure spostarli in un'altra cartella, come descritto nell'articolo:
Spostare i file tra le cartelle di Google Drive con Google Apps Script
https://www.appsscript.it/tutorial/spostare-i-file-tra-le-cartelle-di-google-drive-con-google-apps-script/
grazie infinete ora mi metto a studiare , sei sempre molto gentile
Salve sta studiando questo script (che debbo dire molto interessante) pero' mi da un errore nell'esecuzione alla riga 14
var file = Drive.Files.insert(resource, blob, {ocr: true, ocrLanguage: "it"});
mi dice "drive non definito" dove sto sbagliando (ho attivato le funzionalita' delle api)
https://drive.google.com/open?id=18AQVEyBt3kQHoRsJiCa16E1lFFyUNKY8
grazie :)
Ciao Marco,
oltre ad abilitare le API dalla Console API Google devi attivare le Drive API nei Servizi avanzati di Google dall'editor di script alla voce di menu 'Risorse > Servizi avanzati di Google ...'..
Grazie per il suggerimento dopo aver attivato le drive api mi da queesto errore sempre sulla riga relativa all' ocr Spiacenti. Si è verificato un errore del server. Attendi e riprova. (riga 14, file "Codice") ho provato a dare il link di varie immagini con testo trovate in web sia jpg che png
grazie per tutto
Ciao Marco,
credo sia un problema indipendente dal tuo script.
Prova a svuotare la cache per sicurezza ma probabilmente è un'anomalia temporanea lato Google.
Eventualmente prova a segnalare l'errore nell'issue Tracker come suggerito nel mio articolo relativo a questo tipo di errore generico: https://www.appsscript.it/articoli/google-apps-script-server-not-available.
anch'io sto studiando queste righe di codice che trovo davvero scritte bene , ho notato che lo script funziona se togliamo il riferimento alla lingua {ocr: true, } , se volessi dare alla funzione una serie file invece di un url come debbo fare (i file sono in drive) , sto cercando di rinominare i file con i primi 10 caratteri che vengono letti dall'ocr , se riesco a farlo pubblico lo script
Ciao Mauro,
hai provato a recuperare l'url del file con la funzione getUrl()?
In base alla porzione di codice che ti ho indicato nei primi commenti (che effettua un ciclo sui file all'interno di una cartella), puoi recuperare l'URL del file processato con:
grazie , avevo gia provato mettendogli manualmente ip di un file del drive , ma facendo cosi mi genera un errore tipo "OCR is not supported for files of type text/html (riga 42, file "Codice")" al contrario se gli do un indirizzo internet https://sito.it/foto.jpg lo script funziona regolarmente.. ps buona pasqua a tutti...
Ciao Mauro,
effettuando delle prove su un progetto sul quale sto lavorando ho trovato la soluzione per la conversione di file pdf (anche se il testo all'interno è una scansione) presenti direttamente in Google Drive.
Il codice è esattamente lo stesso proposto nell'articolo, con la differenza che per recuperare il Blob del file la riga di codice da utilizzare è la seguente:
Dove FILE_ID è l'id del file presente su Drive (che puoi recuperare in modo programmatico oppure manualmente cliccando con il tasto destro sul file e poi su 'Ottieni link condivisibile').
Buongiorno, è possibile con app script creare una maschera che intercetta dei pdf all'interno di una cartella di drive in base a nome , cognome all'interno del pdf? Grazie mille William
Ciao William,
quello che mi viene in mente, concettualmente parlando poi lato sviluppo serviranno le dovute accortezze e controlli del caso, è processare i pdf all'interno della cartella su Drive leggendoli uno ad uno tramite OCR (ovvero con la porzione di codice proposta in questo tutorial, con una piccola differenza che ti scrivo qui sotto) in modo da avere il contenuto del testo in una variabile dove poterlo leggere.
Considerando che i tuoi pdf si trovano su Google Drive, per riferirsi ad un file direttamente su Drive anziché su un url esterno, la differenza rispetto al codice del tutorial è alla riga per recuperare il Blob del file, pertanto al posto di questa istruzione:
Utilizzare la seguente:
Dove nel primo caso 'url' si riferisce all'indirizzo fisico del file in rete mentre nel secondo caso, quello che serve a te, FILE_ID è l'id del file presente su Drive.
Michele, davvero molto interessante. Secondo te è possibile Acquisire il testo in una parte specifica del PDF. Per esempio in una determinata area della prima pagina?
Questo perché in questo modo sarebbe possibile rinominare i file, E usare il risultato per indicizzare il file e creare un sistema di archiviazione documentale in base al risultato della scansione .
Ciao Luca,
puoi provare a controllare nella documentazione ufficiale relativa all'API Files:insert: https://developers.google.com/drive/api/v2/reference/files/insert se tra i parametri c'è qualcosa che pensi faccia al caso tuo. A me non sembra che sia previsto questo livello di dettaglio nell'identificare una porzione di una pagina; probabilmente con qualche elaborazione manuale si può riuscire ad ottenere qualcosa ma come riferimento non mi viene in mente altro che possa essere se non il contenuto testuale, quindi poco funzionale e non scalabile.