Existe uma maneira simples de identificar se um PDF é digitalizado?

8

Eu tenho milhares de documentos e alguns deles são digitalizados. Então, preciso de um script para testar todos os arquivos PDF que pertencem a um diretório. Existe uma maneira simples de fazer isso?

  1. A maioria dos PDFs são relatórios. Assim, eles têm muito texto.
  2. Eles são muito diferentes, mas os digitalizados, conforme mencionado abaixo, podem encontrar algum texto devido a um processo precário de OCR acoplado à digitalização.

  3. A proposta devida a Sudodus nos comentários abaixo parece ser muito interessante. Veja a diferença entre um PDF digitalizado para um PDF não digitalizado:

Digitalizado:

grep --color -a 'Image' AR-G1002.pdf
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 340615/Name/Obj13/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 40452/Name/Obj18/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 41680/Name/Obj23/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 41432/Name/Obj28/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 59084/Name/Obj33/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 472681/Name/Obj38/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 469340/Name/Obj43/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 371863/Name/Obj48/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 344092/Name/Obj53/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 59416/Name/Obj58/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 48308/Name/Obj63/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 51564/Name/Obj68/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 63184/Name/Obj73/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 40824/Name/Obj78/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 23320/Name/Obj83/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 31504/Name/Obj93/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 18996/Name/Obj98/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 292932/Name/Obj103/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 27720/Name/Obj108/Subtype/Image/Type/XObject/Width 1698>>stream
               <rdf:li xml:lang="x-default">Image</rdf:li>
               <rdf:li xml:lang="x-default">Image</rdf:li>

Não digitalizado:

grep --color -a 'Image' AR-G1003.pdf
<</Lang(en-US)/MarkInfo<</Marked true>>/Metadata 167 0 R/Pages 2 0 R/StructTreeR<</Contents 4 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F3 9 0 R/F4 11 0 R/F5 13 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/StructParents 0/Tabs/S/Type/<</Filter/FlateDecode/Length 5463>>stream
<</BaseFont/Times#20New#20Roman,Bold/Encoding/WinAnsiEncoding/FirstChar 32/FontD<</Ascent 891/AvgWidth 427/CapHeight 677/Descent -216/Flags 32/FontBBox[-558 -216 2000 677]/FontName/Times#20New#20Roman,Bold/FontWeight 700/ItalicAngle 0/Leadi<</BaseFont/Times#20New#20Roman/Encoding/WinAnsiEncoding/FirstChar 32/FontDescri<</Ascent 891/AvgWidth 401/CapHeight 693/Descent -216/Flags 32/FontBBox[-568 -216 2000 693]/FontName/Times#20New#20Roman/FontWeight 400/ItalicAngle 0/Leading 42<</BaseFont/Arial,Bold/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 10 0<</Ascent 905/AvgWidth 479/CapHeight 728/Descent -210/Flags 32/FontBBox[-628 -210 2000 728]/FontName/Arial,Bold/FontWeight 700/ItalicAngle 0/Leading 33/MaxWidth<</BaseFont/Times#20New#20Roman,Italic/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 12 0 R/LastChar 118/Name/F4/Subtype/TrueType/Type/Font/Widths 164 0 <</Ascent 891/AvgWidth 402/CapHeight 694/Descent -216/Flags 32/FontBBox[-498 -216 1333 694]/FontName/Times#20New#20Roman,Italic/FontWeight 400/ItalicAngle -16.4<</BaseFont/Arial/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 14 0 R/La<</Ascent 905/AvgWidth 441/CapHeight 728/Descent -210/Flags 32/FontBBox[-665 -210 2000 728]/FontName/Arial/FontWeight 400/ItalicAngle 0/Leading 33/MaxWidth 2665<</Contents 16 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F5 13 0 R>>/ProcSet[<</Filter/FlateDecode/Length 7534>>streamarents 1/Tabs/S/Type/Page>>
<</Contents 18 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F5 13 0 R>>/ProcSet[<</Filter/FlateDecode/Length 6137>>streamarents 2/Tabs/S/Type/Page>>
<</Contents 20 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F5 13 0 R/F6 21 0 R><</Filter/FlateDecode/Length 6533>>stream>>/StructParents 3/Tabs/S/Type/Page>>
<</BaseFont/Times#20New#20Roman/DescendantFonts 22 0 R/Encoding/Identity-H/Subty<</BaseFont/Times#20New#20Roman/CIDSystemInfo 24 0 R/CIDToGIDMap/Identity/DW 100<</Ascent 891/AvgWidth 401/CapHeight 693/Descent -216/Flags 32/FontBBox[-568 -216 2000 693]/FontFile2 160 0 R/FontName/Times#20New#20Roman/FontWeight 400/Italic<</Contents 27 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</ExtGState<</GS28 28 0 R/GS29 29 0 R>>/Font<</F1 5 0 R/F2 7 0 R/F3 9 0 R/F5 13 0 R/F6 21 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC<</Filter/FlateDecode/Length 5369>>streamge>>

O número de imagens por página é muito maior (cerca de uma por página)!

DanielTheRocketMan
fonte
7
Você quer dizer se são texto ou imagens?
DK Bose
8
Por que você quer saber se um arquivo pdf é digitalizado ou não? Como você pretende usar essas informações?
sudodus 19/11/19
4
@sudodus Faz uma pergunta muito boa. Por exemplo, a maioria dos PDFs digitalizados tem seu texto disponível para seleção, convertido usando OCR. Você faz a diferença entre esses arquivos e arquivos de texto? Você conhece a fonte dos seus PDFs?
pipe
1
Existe alguma diferença nos metadados dos documentos digitalizados e não digitalizados? Isso ofereceria uma maneira muito limpa e fácil.
dessert
1
Se um pdfarquivo contém uma imagem (inserida em um documento ao lado do texto ou em páginas inteiras, 'pdf digitalizado'), o arquivo geralmente (talvez sempre) contém a string /Image/, que pode ser encontrada na linha de comando grep --color -a 'Image' filename.pdf. Isso separará os arquivos que contêm apenas texto daqueles que contêm imagens (imagens de página inteira, bem como páginas de texto com logotipos pequenos e figuras ilustrativas de tamanho médio).
sudodus 19/11/19

Respostas:

4

Shellscript

  • Se um pdfarquivo contém uma imagem (inserida em um documento ao lado do texto ou em páginas inteiras, 'pdf digitalizado'), o arquivo geralmente (talvez sempre) contém a sequência /Image/.

  • Da mesma maneira, você pode procurar a string /Textpara saber se um arquivo pdf contém texto (não digitalizado).

Eu criei o shellscript pdf-text-or-imagee ele pode funcionar na maioria dos casos com seus arquivos. O shellscript procura as seqüências de texto /Image/e /Textos pdfarquivos.

#!/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

Torne o shellscript executável,

chmod ugo+x pdf-text-or-image

Mude o diretório para onde você tem os pdfarquivos e execute o shellscript.

Arquivos identificados são movidos para os seguintes subdiretórios

  • scanned
  • text
  • s-and-t (para documentos com imagens [digitalizadas?] e conteúdo de texto)

Objetos de arquivo não identificados, 'UFOs', permanecem no diretório atual.

Teste

Testei o shellscript com dois dos seus arquivos, AR-G1002.pdfe AR-G1003.pdf, e com alguns próprios pdfarquivos (que criei usando o 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

Vamos torcer para que

  • não há UFOs no seu conjunto de arquivos
  • a classificação está correta em relação ao texto versus imagens digitalizadas
sudodus
fonte
em vez de redirecionar para / dev / null você pode apenas usargrep -q
phuclv
1
@ phuclv, Obrigado pela dica :-) Isso também torna um pouco mais rápido, principalmente em arquivos grandes, porque grep -qsai imediatamente com status zero se alguma correspondência for encontrada (em vez de pesquisar nos arquivos inteiros).
sudodus
6
  1. Coloque todos os arquivos .pdf em uma pasta.
  2. Nenhum arquivo .txt nessa pasta.
  3. No terminal, altere o diretório para essa pasta com cd <path to dir>
  4. Crie mais um diretório para arquivos não verificados. Exemplo:
mkdir ./x 
for file in *.pdf; do
    if [ $(pdftotext "$file")"x" == "x" ] ; then mv "$file" ./x; fi
rm *.txt
done

Todos os arquivos digitalizados em PDF permanecerão na pasta e outros arquivos serão movidos para outra pasta.

Vijay
fonte
isso é ótimo. No entanto, esse arquivo vai para a outra pasta e é verificado: drive.google.com/open?id=12xIQdRo_cyTf27Ck6DQKvRyRvlkYEzjl O que está acontecendo?
DanielTheRocketMan
8
Os PDFs digitalizados geralmente sempre contêm o conteúdo de texto OCR, portanto, acho que esse teste simples falharia para eles. Um indicador melhor pode ser uma imagem grande por página, independentemente do conteúdo do texto.
Joey
2
Voto negativo devido à falha muito óbvia: como você sabe se os arquivos são verificados ou não? É isso que o OP está perguntando: como testar programaticamente a verificação ou não.
jamesqf
1
@DanielTheRocketMan A versão do arquivo PDF provavelmente está afetando a ferramenta que você está usando para selecionar texto. A saída de file pdf-filename.pdfproduzirá um número de versão. Não foi possível pesquisar por texto específico em BR-L1411-3.pdf BR-L1411-3.pdf: documento PDF, versão 1.3, mas consegui pesquisar por texto nos dois arquivos que você forneceu, que são a versão 1.5 e 1.6 e obtenha uma ou mais correspondências. Usei o visualizador de PDF XChange para pesquisar esses arquivos, mas obtive resultados semelhantes com o evince. o documento da versão 1.3 não correspondia a nada.
Elder Geek
1
@DanielTheRocketMan Se for esse o caso, você poderá classificar os documentos por versão usando a saída fileútil para concluir seu projeto. Embora eu, ao que parece, outros ainda não estejam claros sobre exatamente o que você está tentando realizar.
Elder Geek
2

Criei um script para detectar se um PDF era OCRd. A idéia principal: nos PDFs do OCRd, o texto é invisível.

Algoritmo para testar se um determinado PDF ( f1) era OCRd:

  1. crie uma cópia do f1anotado comof2
  2. excluir todo o texto em f2
  3. crie imagens (PNG) para todas (ou apenas algumas) páginas para f1ef2
  4. f1foi OCRd se todas as imagens f1e f2forem idênticas.

https://github.com/jfilter/pdf-scripts/blob/master/is_ocrd_pdf.sh

#!/usr/bin/env bash
set -e
set -x

################################################################################
# Check if a PDF was scanned or created digitally, works on OCRd PDFs
#
# Usage:
#   bash is_scanned_pdf.sh [-p] file
#
#   Exit 0: Yes, file is a scanned PDF
#   Exit 99: No, file was created digitally
#
# Arguments:
#   -p or --pages: pos. integer, only consider first N pages
#
# Please report issues at https://github.com/jfilter/pdf-scripts/issues
#
# GPLv3, Copyright (c) 2020 Johannes Filter
################################################################################

# parse arguments
# h/t https://stackoverflow.com/a/33826763/4028896
max_pages=-1
# skip over positional argument of the file(s), thus -gt 1
while [[ "$#" -gt 1 ]]; do
  case $1 in
  -p | --pages)
    max_pages="$2"
    shift
    ;;
  *)
    echo "Unknown parameter passed: $1"
    exit 1
    ;;
  esac
  shift
done

# increment to make it easier with page numbering
max_pages=$((max_pages++))

command_exists() {
  if ! [ -x $($(command -v $1 &>/dev/null)) ]; then
    echo $(error: $1 is not installed.) >&2
    exit 1
  fi
}

command_exists mutool && command_exists gs && command_exists compare
command_exists pdfinfo

orig=$PWD
num_pages=$(pdfinfo $1 | grep Pages | awk '{print $2}')

echo $num_pages

echo $max_pages

if ((($max_pages > 1) && ($max_pages < $num_pages))); then
  num_pages=$max_pages
fi

cd $(mktemp -d)

for ((i = 1; i <= num_pages; i++)); do
  mkdir -p output/$i && echo $i
done

# important to filter text on output of GS (tmp1), cuz GS alters input PDF...
gs -o tmp1.pdf -sDEVICE=pdfwrite -dLastPage=$num_pages $1 &>/dev/null
gs -o tmp2.pdf -sDEVICE=pdfwrite -dFILTERTEXT tmp1.pdf &>/dev/null
mutool convert -o output/%d/1.png tmp1.pdf 2>/dev/null
mutool convert -o output/%d/2.png tmp2.pdf 2>/dev/null

for ((i = 1; i <= num_pages; i++)); do
  echo $i
  # difference in pixels, if 0 there are the same pictures
  # discard diff image
  if ! compare -metric AE output/$i/1.png output/$i/2.png null: 2>&1; then
    echo " pixels difference, not a scanned PDF, mismatch on page $i"
    exit 99
  fi
done
Johannes Filter
fonte
1

O Hobbyist oferece uma boa solução se os documentos digitalizados da coleção de documentos não tiverem texto adicionado com reconhecimento óptico de caracteres (OCR). Se isso for possível, convém executar alguns scripts que leiam a saída pdfinfo -metae verifiquem a ferramenta usada para criar o arquivo, ou utilize uma rotina Python que use uma das bibliotecas Python para examiná-las. A pesquisa de texto com uma ferramenta como stringsnão será confiável, pois o conteúdo do PDF pode ser compactado. E verificar a ferramenta de criação também não é à prova de falhas, pois as páginas PDF podem ser combinadas; Eu costumo combinar documentos de texto PDF com imagens digitalizadas para manter as coisas juntas.

Lamento não poder oferecer sugestões específicas. Já faz um tempo desde que eu analisei a estrutura interna do PDF, mas dependendo de quão rigorosos são seus requisitos, você pode querer saber que é meio complicado. Boa sorte!

ichabod
fonte
2
Também estou tentando usar python, mas não é trivial saber se um pdf é digitalizado ou não. O ponto é que mesmo os documentos que você não pode selecionar texto apresentam algum texto quando ele é convertido em txt. Por exemplo, estou usando o minerador de pdf no Python e posso encontrar algum texto na conversão, mesmo para PDFs que a ferramenta de seleção não funciona.
DanielTheRocketMan
1

Se realmente se trata de detectar se o PDF foi criado pela digitalização, em vez de o PDF possuir imagens em vez de texto , pode ser necessário cavar os metadados do arquivo, não apenas o conteúdo.

Em geral, para os arquivos que eu encontrei no meu computador e nos arquivos de teste, o seguinte é verdadeiro:

  • Os arquivos digitalizados possuem menos de 1000 caracteres / página versus os não digitalizados que sempre têm mais de 1000 caracteres / página
  • Vários arquivos digitalizados independentes tinham "Canon" listado como criador do PDF, provavelmente fazendo referência ao software do scanner Canon
  • É provável que os PDFs com "Microsoft Word" como criador não sejam digitalizados, pois são exportações de palavras. Mas alguém pode digitalizar para o Word e depois exportar para PDF - algumas pessoas têm um fluxo de trabalho muito estranho .

Estou usando o Windows no momento, então usei node.jso seguinte exemplo:

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("\n\nFILE: ", 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;
}

Para executá-lo, você precisa ter o Node.js instalado (deve ser um único comando) e também precisa chamar:

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

Este exemplo não é considerado uma solução finalizada, mas com o debugsinalizador, você obtém algumas informações sobre as meta informações de um arquivo:

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:\web\so-odpovedi\pdf\BR-L1411-3-scanned.pdf

A função ingênua que escrevi tem 100% de êxito nos documentos que encontrei no meu computador (incluindo suas amostras). Eu nomeei os arquivos com base em qual era seu status antes de executar o programa, para possibilitar ver se os resultados estão corretos.

D:\xxxx\pdf>node detect_scanned.js scanned
D:\xxxx\pdf\AR-G1002-scanned.pdf
D:\xxxx\pdf\AR-G1002_scanned.pdf
D:\xxxx\pdf\BR-L1411-3-scanned.pdf
D:\xxxx\pdf\WHO_TRS_696-scanned.pdf

D:\xxxx\pdf>node detect_scanned.js
D:\xxxx\pdf\AR-G1003-not-scanned.pdf
D:\xxxx\pdf\ASEE_-_thermoelectric_paper_-_final-not-scanned.pdf
D:\xxxx\pdf\MULTIMODE ABSORBER-not-scanned.pdf
D:\xxxx\pdf\ReductionofOxideMineralsbyHydrogenPlasma-not-scanned.pdf

Você pode usar o modo de depuração junto com um pouquinho de programação para melhorar bastante seus resultados. Você pode passar a saída do programa para outros programas, ele sempre terá um caminho completo por linha.

Tomáš Zato - Restabelecer Monica
fonte
Re "Microsoft Word" como criador, isso vai depender da fonte dos documentos originais. Se, por exemplo, são trabalhos científicos, muitos, se não a maioria, foram criados por algo da cadeia de ferramentas LaTeX.
Jamesqf #
0

2 maneiras em que posso pensar:

  1. Usando a ferramenta Selecionar texto: se você estiver usando um PDF digitalizado, os textos não poderão ser selecionados, uma caixa será exibida. Você pode usar esse fato para criar o script. Eu sei que em C ++ QT existe uma maneira, mas não tenho certeza no Linux.

  2. Pesquisar palavra no arquivo: em um PDF não digitalizado, sua pesquisa funcionará, mas não no arquivo digitalizado. Você só precisa encontrar algumas palavras comuns a todos os PDFs ou prefiro procurar a letra 'e' em todos os PDFs. Ele tem a distribuição de frequência mais alta, então é provável que você o encontre em todos os documentos que possuem texto (a menos que seja por engano )

por exemplo

grep -rnw '/path/to/pdf/' -e 'e'

Use qualquer uma das ferramentas de processamento de texto

swapedoc
fonte
1
um PDF digitalizado também pode ter textos selecionáveis porque OCR não é uma coisa estranha hoje em dia e até mesmo muitos leitores de PDF livres têm OCR recurso
phuclv
@ phuclv: Mas se o arquivo foi convertido em texto com OCR, ele não é mais um arquivo "digitalizado", pelo menos pelo que entendi o objetivo do OP. Embora você realmente tenha agora três tipos de arquivos pdf: texto ab initio, texto de OCR e "texto" que é uma imagem digitalizada.
jamesqf
1
@jamesqf, veja o exemplo acima. Eles são digitalizados em pdf. Não consigo recuperar a maior parte do texto usando um pdfminer convencional.
DanielTheRocketMan
1
Eu acho que as necessidades op a repensar / reformular a definição de digitalizada nesse caso ou parar de usar o Acrobat X, que leva cópia digitalizada e leva-lo como um ocr, em vez de imagem
swapedoc