Existe-t-il un moyen simple d'identifier si un PDF est numérisé?

8

J'ai des milliers de documents et certains d'entre eux sont numérisés. J'ai donc besoin d'un script pour tester tous les fichiers PDF qui appartiennent à un répertoire. Existe-t-il un moyen simple de le faire?

  1. La plupart des PDF sont des rapports. Ils ont donc beaucoup de texte.
  2. Ils sont très différents, mais ceux numérisés comme mentionné ci-dessous peuvent trouver du texte en raison d'un processus OCR précaire couplé à la numérisation.

  3. La proposition due à Sudodus dans les commentaires ci-dessous semble être très intéressante. Regardez la différence entre un PDF numérisé et un PDF non numérisé:

Numérisé:

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>

Non numérisé:

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>>

Le nombre d'images par page est beaucoup plus important (environ une par page)!

DanielTheRocketMan
la source
7
Voulez-vous dire s'il s'agit de texte ou d'images?
DK Bose
8
Pourquoi voulez-vous savoir si un fichier pdf est scanné ou non? Comment comptez-vous utiliser ces informations?
sudodus
4
@sudodus pose une très bonne question. Par exemple, la plupart des PDF numérisés ont leur texte disponible pour la sélection, converti en utilisant l'OCR. Faites-vous une différence entre ces fichiers et les fichiers texte? Avez - vous connaissez la source de vos fichiers PDF?
pipe
1
Y a-t-il une différence dans les métadonnées des documents numérisés et non numérisés? Cela offrirait un moyen très propre et facile.
dessert
1
Si un pdffichier contient une image (insérée dans un document à côté de texte ou sous forme de pages entières, 'pdf numérisé'), le fichier contient souvent (peut-être toujours) la chaîne /Image/, qui peut être trouvée avec la ligne de commande grep --color -a 'Image' filename.pdf. Cela séparera les fichiers qui ne contiennent que du texte de ceux contenant des images (images pleine page ainsi que pages de texte avec de petits logos et images illustratives de taille moyenne).
sudodus

Réponses:

4

Shellscript

  • Si un pdffichier contient une image (insérée dans un document à côté de texte ou sous forme de pages entières, «pdf numérisé»), le fichier contient souvent (peut-être toujours) la chaîne /Image/.

  • De la même manière, vous pouvez rechercher la chaîne /Textpour savoir si un fichier pdf contient du texte (non numérisé).

J'ai fait le shellscript pdf-text-or-image, et cela pourrait fonctionner dans la plupart des cas avec vos fichiers. Le shellscript recherche les chaînes de texte /Image/et /Textles pdffichiers.

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

Rendez le shellscript exécutable,

chmod ugo+x pdf-text-or-image

Changez le répertoire où vous avez les pdffichiers et exécutez le shellscript.

Les fichiers identifiés sont déplacés vers les sous-répertoires suivants

  • scanned
  • text
  • s-and-t (pour les documents contenant à la fois des images [numérisées?] et du texte)

Les objets fichier non identifiés, les «OVNIS», restent dans le répertoire courant.

Tester

Je l' ai testé le shellscript avec deux de vos fichiers, AR-G1002.pdfet AR-G1003.pdf, et avec quelques propres pdffichiers (que j'ai créés avec 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

Espérons que

  • il n'y a pas d'OVNIS dans votre ensemble de fichiers
  • le tri est correct concernant le texte par rapport aux images numérisées /
sudodus
la source
au lieu de rediriger vers / dev / null, vous pouvez simplement utilisergrep -q
phuclv
1
@phuclv, merci pour l'astuce :-) Cela le rend aussi un peu plus rapide, en particulier avec les gros fichiers, car il se grep -qferme immédiatement avec un état nul si une correspondance est trouvée (au lieu de parcourir tous les fichiers).
sudodus
6
  1. Mettez tous les fichiers .pdf dans un dossier.
  2. Aucun fichier .txt dans ce dossier.
  3. Dans le terminal, changez de répertoire vers ce dossier avec cd <path to dir>
  4. Créez un autre répertoire pour les fichiers non numérisés. Exemple:
mkdir ./x 
for file in *.pdf; do
    if [ $(pdftotext "$file")"x" == "x" ] ; then mv "$file" ./x; fi
rm *.txt
done

Tous les fichiers numérisés en pdf resteront dans le dossier et les autres fichiers seront déplacés vers un autre dossier.

Vijay
la source
c'est bien. Cependant, ce fichier va dans l'autre dossier et il est analysé: drive.google.com/open?id=12xIQdRo_cyTf27Ck6DQKvRyRvlkYEzjl Que se passe-t-il?
DanielTheRocketMan
8
Les PDF numérisés contiennent souvent toujours le contenu texte OCRed, donc je suppose qu'un simple test échouerait pour eux. Un meilleur indicateur pourrait être une grande image par page, quel que soit le contenu du texte.
Joey
2
Downvoted en raison de la faille très évidente: comment savoir si les fichiers sont scannés ou non en premier lieu? C'est ce que l'OP demande: comment tester par programme les scannés ou non.
jamesqf
1
@DanielTheRocketMan La version du fichier PDF a probablement un impact sur l'outil que vous utilisez pour sélectionner du texte. La sortie de file pdf-filename.pdfproduira un numéro de version. Je n'ai pas pu rechercher de texte spécifique dans BR-L1411-3.pdf BR-L1411-3.pdf: document PDF, version 1.3, mais j'ai pu rechercher du texte dans les deux autres fichiers que vous avez fournis, qui sont la version 1.5 et 1.6 et obtenez un ou plusieurs matchs. J'ai utilisé la visionneuse PDF XChange pour rechercher ces fichiers, mais j'ai obtenu des résultats similaires avec evince. le document de la version 1.3 ne correspondait à rien.
Elder Geek
1
@DanielTheRocketMan Si tel est le cas, vous pourriez trouver le tri des documents par version en utilisant la sortie fileutile pour terminer votre projet. Bien qu'il me semble que d' autres ne savent toujours pas exactement ce que vous essayez d'accomplir.
Elder Geek
2

J'ai créé un script pour détecter si un PDF était OCRd. L'idée principale: dans les PDF OCRd, le texte est invisible.

Algorithme pour tester si un PDF ( f1) donné était OCRd:

  1. créer une copie de f1noté commef2
  2. supprimer tout le texte sur f2
  3. créer des images (PNG) pour toutes (ou seulement quelques) pages pour f1etf2
  4. f1était OCRd si toutes les images de f1et f2sont identiques.

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
Filtre Johannes
la source
1

Hobbyist offre une bonne solution si les documents numérisés de la collection de documents n'ont pas de texte ajouté avec reconnaissance optique de caractères (OCR). Si cela est possible, vous souhaiterez peut-être effectuer un script qui lit la sortie de pdfinfo -metaet vérifie l'outil utilisé pour créer le fichier, ou utiliser une routine Python qui utilise l'une des bibliothèques Python pour les examiner. La recherche de texte avec un outil comme stringsne sera pas fiable car le contenu PDF peut être compressé. Et la vérification de l'outil de création n'est pas non plus infaillible, car les pages PDF peuvent être combinées; Je combine régulièrement des documents texte PDF avec des images numérisées pour garder les choses ensemble.

Je suis désolé de ne pouvoir offrir de suggestions spécifiques. Cela fait un moment que je n'ai pas fouillé la structure interne du PDF, mais selon la rigueur de vos exigences, vous voudrez peut-être savoir que c'est un peu compliqué. Bonne chance!

ichabod
la source
2
J'essaie également d'utiliser python, mais il n'est pas trivial de savoir si un pdf est scanné ou non. Le fait est que même les documents que vous ne pouvez pas sélectionner de texte présentent du texte lors de leur conversion en txt. Par exemple, j'utilise un mineur de pdf en Python et je peux trouver du texte dans la conversion même pour les fichiers PDF qui sélectionnent l'outil ne fonctionne pas.
DanielTheRocketMan
1

S'il s'agit davantage de détecter réellement si le PDF a été créé par numérisation plutôt que si le PDF contient des images au lieu de texte, vous devrez peut-être fouiller dans les métadonnées du fichier, pas seulement le contenu.

En général, pour les fichiers que j'ai pu trouver sur mon ordinateur et vos fichiers de test, ce qui suit est vrai:

  • Les fichiers numérisés ont moins de 1 000 caractères / page par rapport aux fichiers non numérisés qui ont toujours plus de 1 000 caractères / page
  • Plusieurs fichiers numérisés indépendants avaient "Canon" répertorié comme le créateur de PDF, faisant probablement référence au logiciel de numérisation Canon
  • Les fichiers PDF avec "Microsoft Word" en tant que créateur sont susceptibles de ne pas être numérisés, car ils sont des exportations de mots. Mais quelqu'un pourrait numériser au format Word, puis exporter au format PDF - certaines personnes ont un flux de travail très étrange .

J'utilise Windows pour le moment, j'ai donc utilisé node.jsl'exemple suivant:

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;
}

Pour l'exécuter, vous devez avoir installé Node.js (devrait être une seule commande) et vous devez également appeler:

npm install mz pdf-parse

Usage:

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

Cet exemple n'est pas considéré comme une solution terminée, mais avec l' debugindicateur, vous obtenez un aperçu des méta-informations d'un fichier:

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

La fonction naïve que j'ai écrite a 100% de succès sur les documents que j'ai pu trouver sur mon ordinateur (y compris vos échantillons). J'ai nommé les fichiers en fonction de leur état avant d'exécuter le programme, pour permettre de voir si les résultats sont corrects.

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

Vous pouvez utiliser le mode débogage avec un tout petit peu de programmation pour améliorer considérablement vos résultats. Vous pouvez passer la sortie du programme à d'autres programmes, il aura toujours un chemin complet par ligne.

Tomáš Zato - Réintégrer Monica
la source
Re "Microsoft Word" en tant que créateur, cela va dépendre de la source des documents originaux. Si par exemple ce sont des articles scientifiques, beaucoup sinon la plupart vont avoir été créés par quelque chose dans la chaîne d'outils LaTeX.
jamesqf
0

2 façons de penser:

  1. Utilisation de l'outil de sélection de texte: si vous utilisez un PDF numérisé, les textes ne peuvent pas être sélectionnés, une boîte apparaîtra plutôt. Vous pouvez utiliser ce fait pour créer le script. Je sais qu'en C ++ QT il y a un moyen, mais je ne suis pas sûr sous Linux.

  2. Rechercher un mot dans un fichier: dans un PDF non numérisé, votre recherche fonctionnera, mais pas dans un fichier numérisé. Vous avez juste besoin de trouver des mots communs à tous les PDF ou je préfère dire rechercher la lettre «e» dans tous les PDF. Il a la distribution de fréquences la plus élevée, il y a donc de fortes chances que vous le trouviez dans tous les documents contenant du texte (à moins que ce ne soit gadsby )

par exemple

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

Utilisez l'un des outils de traitement de texte

swapedoc
la source
1
un PDF numérisé peut également avoir des textes sélectionnables car l'OCR n'est pas une chose étrange de nos jours et même de nombreux lecteurs PDF gratuits ont une fonction OCR
phuclv
@phuclv: Mais si le fichier a été converti en texte avec OCR, ce n'est plus un fichier "scanné", du moins si je comprends le but de l'OP. Bien que vous ayez vraiment maintenant 3 types de fichiers pdf: texte ab initio, texte de l'OCR et "texte" qui est une image numérisée.
jamesqf
1
@jamesqf veuillez regarder l'exemple ci-dessus. Ils sont scannés en pdf. La plupart du texte que je ne peux pas récupérer en utilisant un pdfminer conventionnel.
DanielTheRocketMan
1
je pense que l'op doit repenser / reformuler la définition de numérisé dans ce cas ou cesser d'utiliser acrobat x, qui prend la copie numérisée et la prend comme ocr plutôt que comme image
swapedoc