Skip to content

Esiste un modo semplice per identificare se un PDF è stato scansionato?

Questa recensione è stata approvata da specialisti, quindi garantiamo l'accuratezza della nostra recensione.

Soluzione:

  1. Mettere tutti i file .pdf in una cartella.
  2. Nessun file .txt nella cartella.
  3. Nel terminale cambiare la directory in quella cartella con cd
  4. Creare un'altra cartella per i file non scansionati. Esempio:
mkdir ./x 
for file in *.pdf; do
    if [ $(pdftotext "$file")"x" == "x" ] ; then mv "$file" ./x; fi
rm *.txt
done

Tutti i file pdf scansionati rimarranno nella cartella e gli altri file verranno spostati in un'altra cartella.

Shellscript

  • Se un pdf contiene un'immagine (inserita in un documento accanto al testo o come pagine intere, 'pdf scansionato'), il file spesso (forse sempre) contiene la stringa /Image/.

  • Allo stesso modo è possibile cercare la stringa /Text per sapere se un file pdf contiene testo (non scansionato).

Ho creato lo shellscript pdf-text-or-imagee potrebbe funzionare nella maggior parte dei casi con i vostri file. Lo shellscript cerca le stringhe di testo /Image/ e /Text nel file pdf file.

#!/bin/bash

echo "shellscript $0"
ls --color --group-directories-first
read -p "Is it OK to use this shellscript in this directory? (y/N) " ans
if [ "$ans" != "y" ]
then
 exit
fi

mkdir -p scanned
mkdir -p text
mkdir -p "s-and-t"

for file in *.pdf
do
 grep -aq '/Image/' "$file"
 if [ $? -eq 0 ]
 then
  image=true
 else
  image=false
 fi
 grep -aq '/Text' "$file"
 if [ $? -eq 0 ]
 then
  text=true
 else
  text=false
 fi

 if $image && $text
 then
  mv "$file" "s-and-t"
 elif $image
 then
  mv "$file" "scanned"
 elif $text
 then
  mv "$file" "text"
 else
  echo "$file undecided"
 fi
done

Rendere eseguibile lo shellscript,

chmod ugo+x pdf-text-or-image

Cambiare la directory in cui si trovano i file pdf ed eseguire lo shellscript.

I file identificati vengono spostati nelle seguenti sottodirectory

  • scanned
  • text
  • s-and-t (per i documenti con entrambi i file [scanned?] immagini e contenuto testuale)

Gli oggetti file non identificati, 'UFO', rimangono nella directory corrente.

Test

Ho testato lo shellscript con due dei vostri file, AR-G1002.pdf e AR-G1003.pdfe con alcuni propri file pdf (che ho creato utilizzando Libre Office Impress).

$ ./pdf-text-or-image
shellscript ./pdf-text-or-image
s-and-t                                 mkUSB-quick-start-manual-11.pdf    mkUSB-quick-start-manual-nox-11.pdf
scanned                                 mkUSB-quick-start-manual-12-0.pdf  mkUSB-quick-start-manual-nox.pdf
text                                    mkUSB-quick-start-manual-12.pdf    mkUSB-quick-start-manual.pdf
AR-G1002.pdf                            mkUSB-quick-start-manual-74.pdf    OBI-quick-start-manual.pdf
AR-G1003.pdf                            mkUSB-quick-start-manual-75.pdf    oem.pdf
DescriptionoftheOneButtonInstaller.pdf  mkUSB-quick-start-manual-8.pdf     pdf-text-or-image
GrowIt.pdf                              mkUSB-quick-start-manual-9.pdf     pdf-text-or-image0
list-files.pdf                          mkUSB-quick-start-manual-bas.pdf   README.pdf
Is it OK to use this shellscript in this directory? (y/N) y

$ ls -1 *
pdf-text-or-image
pdf-text-or-image0

s-and-t:
DescriptionoftheOneButtonInstaller.pdf
GrowIt.pdf
mkUSB-quick-start-manual-11.pdf
mkUSB-quick-start-manual-12-0.pdf
mkUSB-quick-start-manual-12.pdf
mkUSB-quick-start-manual-8.pdf
mkUSB-quick-start-manual-9.pdf
mkUSB-quick-start-manual.pdf
OBI-quick-start-manual.pdf
README.pdf

scanned:
AR-G1002.pdf

text:
AR-G1003.pdf
list-files.pdf
mkUSB-quick-start-manual-74.pdf
mkUSB-quick-start-manual-75.pdf
mkUSB-quick-start-manual-bas.pdf
mkUSB-quick-start-manual-nox-11.pdf
mkUSB-quick-start-manual-nox.pdf
oem.pdf

Speriamo che

  • non ci siano UFO nel vostro insieme di file
  • l'ordinamento sia corretto per quanto riguarda il testo rispetto alle immagini scannerizzate

Se si tratta di rilevare effettivamente se il PDF è stato creato dalla scansione piuttosto che il pdf ha immagini invece di testo allora potrebbe essere necessario scavare nei metadati del file, non solo nel contenuto.

In generale, per i file che ho trovato sul mio computer e per i vostri file di prova, è vero quanto segue:

  • I file scansionati hanno meno di 1000caratteri/pagina rispetto a quelli non scansionati che hanno sempre più di 1000caratteri/pagina.
  • Diversi file scansionati indipendenti riportavano "Canon" come creatore di PDF, probabilmente riferendosi al software dello scanner Canon.
  • È probabile che i PDF con "Microsoft Word" come creatore non siano stati scansionati, in quanto si tratta di esportazioni di Word. Ma qualcuno potrebbe scansionare in Word e poi esportare in PDF: alcune persone hanno un flusso di lavoro molto strano.

Al momento sto usando Windows, quindi ho usato node.js per il seguente esempio:

const fs = require("mz/fs");
const pdf_parse = require("pdf-parse");
const path = require("path");

const SHOW_SCANNED_ONES = process.argv.indexOf("scanned") != -1;

const DEBUG = process.argv.indexOf("debug") != -1;
const STRICT = process.argv.indexOf("strict") != -1;

const debug = DEBUG ? console.error : () => { };

(async () => {
    const pdfs = (await fs.readdir(".")).filter((fname) => { return fname.endsWith(".pdf") });

    for (let i = 0, l = pdfs.length; i < l; ++i) {
        const pdffilename = pdfs[i];
        try {
            debug("nnFILE: ", pdffilename);
            const buffer = await fs.readFile(pdffilename);
            const data = await pdf_parse(buffer);

            if (!data.info)
                data.indo = {};
            if (!data.metadata) {
                data.metadata = {
                    _metadata: {}
                };
            }

            // PDF info
            debug(data.info);
            // PDF metadata
            debug(data.metadata);
            // text length
            const textLen = data.text ? data.text.length : 0;
            const textPerPage = textLen / (data.numpages);
            debug("Text length: ", textLen);
            debug("Chars per page: ", textLen / data.numpages);
            // PDF.js version
            // check https://mozilla.github.io/pdf.js/getting_started/
            debug(data.version);

            if (evalScanned(data, textLen, textPerPage) == SHOW_SCANNED_ONES) {
                console.log(path.resolve(".", pdffilename));
            }
        }
        catch (e) {
            if (strict && !debug) {
                console.error("Failed to evaluate " + item);
            }
            {
                debug("Failed to evaluate " + item);
                debug(e.stack);
            }
            if (strict) {
                process.exit(1);
            }
        }
    }
})();
const IS_CREATOR_CANON = /canon/i;
const IS_CREATOR_MS_WORD = /microsoft.*?word/i;
// just defined for better clarity or return values
const IS_SCANNED = true;
const IS_NOT_SCANNED = false;
function evalScanned(pdfdata, textLen, textPerPage) {
    if (textPerPage < 300 && pdfdata.numpages>1) {
        // really low number, definitelly not text pdf
        return IS_SCANNED;
    }
    // definitelly has enough text
    // might be scanned but OCRed
    // we return this if no 
    // suspition of scanning is found
    let implicitAssumption = textPerPage > 1000 ? IS_NOT_SCANNED : IS_SCANNED;
    if (IS_CREATOR_CANON.test(pdfdata.info.Creator)) {
        // this is always scanned, canon is brand name
        return IS_SCANNED;
    }
    return implicitAssumption;
}

Per eseguirlo, è necessario avere installato Node.js (dovrebbe essere un singolo comando) e bisogna anche chiamare:

npm install mz pdf-parse

Uso:

node howYouNamedIt.js [scanned] [debug] [strict]

 - scanned show PDFs thought to be scanned (otherwise shows not scanned)
 - debug shows the debug info such as metadata and error stack traces
 - strict kills the program on first error

Questo esempio non è considerato una soluzione finita, ma con l'opzione debug si possono ottenere alcune informazioni sulle meta-informazioni di un file:

FILE:  BR-L1411-3-scanned.pdf
{ PDFFormatVersion: '1.3',
  IsAcroFormPresent: false,
  IsXFAPresent: false,
  Creator: 'Canon ',
  Producer: ' ',
  CreationDate: 'D:20131212150500-03'00'',
  ModDate: 'D:20140709104225-03'00'' }
Metadata {
  _metadata:
   { 'xmp:createdate': '2013-12-12T15:05-03:00',
     'xmp:creatortool': 'Canon',
     'xmp:modifydate': '2014-07-09T10:42:25-03:00',
     'xmp:metadatadate': '2014-07-09T10:42:25-03:00',
     'pdf:producer': '',
     'xmpmm:documentid': 'uuid:79a14710-88e2-4849-96b1-512e89ee8dab',
     'xmpmm:instanceid': 'uuid:1d2b2106-a13f-48c6-8bca-6795aa955ad1',
     'dc:format': 'application/pdf' } }
Text length:  772
Chars per page:  2
1.10.100
D:webso-odpovedipdfBR-L1411-3-scanned.pdf

La funzione ingenua che ho scritto ha avuto un successo del 100% sui documenti che ho trovato sul mio computer (compresi i vostri esempi). Ho nominato i file in base al loro stato prima dell'esecuzione del programma, per poter vedere se i risultati sono corretti.

D:xxxxpdf>node detect_scanned.js scanned
D:xxxxpdfAR-G1002-scanned.pdf
D:xxxxpdfAR-G1002_scanned.pdf
D:xxxxpdfBR-L1411-3-scanned.pdf
D:xxxxpdfWHO_TRS_696-scanned.pdf

D:xxxxpdf>node detect_scanned.js
D:xxxxpdfAR-G1003-not-scanned.pdf
D:xxxxpdfASEE_-_thermoelectric_paper_-_final-not-scanned.pdf
D:xxxxpdfMULTIMODE ABSORBER-not-scanned.pdf
D:xxxxpdfReductionofOxideMineralsbyHydrogenPlasma-not-scanned.pdf

È possibile utilizzare la modalità di debug insieme a un minimo di programmazione per migliorare notevolmente i risultati. È possibile passare l'output del programma ad altri programmi, che avranno sempre un percorso completo per riga.

valutazioni e commenti

Se hai trovato utile il nostro articolo, ti saremmo grati se lo condividessi con altri sviluppatori e ci aiutassi a diffondere i nostri contenuti.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.