AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1094198
Accepted
DanielTheRocketMan
DanielTheRocketMan
Asked: 2018-11-20 04:00:10 +0800 CST2018-11-20 04:00:10 +0800 CST 2018-11-20 04:00:10 +0800 CST

是否有一种简单的方法来识别 PDF 是否被扫描?

  • 772

我有数千份文件,其中一些被扫描了。所以我需要一个脚本来测试属于一个目录的所有 PDF 文件。有没有一种简单的方法可以做到这一点?

  1. 大多数 PDF 是报告。因此,他们有很多文字。
  2. 它们非常不同,但是由于与扫描相关的不稳定的 OCR 过程,如下所述的扫描的可以找到一些文本。

    • 未扫描
    • 已扫描1
    • 已扫描2
  3. 下面评论中由于 Sudodus 的提议似乎很有趣。查看已扫描的 PDF 与未扫描的 PDF 之间的区别:

扫描:

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>

未扫描:

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

每页的图像数量要大得多(大约每页一张)!

command-line pdf
  • 7 7 个回答
  • 13366 Views

7 个回答

  • Voted
  1. Vijay
    2018-11-20T05:35:42+08:002018-11-20T05:35:42+08:00
    1. 将所有 .pdf 文件放在一个文件夹中。
    2. 该文件夹中没有 .txt 文件。
    3. 在终端更改目录到该文件夹cd <path to dir>
    4. 为未扫描的文件再创建一个目录。例子:
    mkdir ./x 
    for file in *.pdf; do
        if [ $(pdftotext "$file")"x" == "x" ] ; then mv "$file" ./x; fi
    rm *.txt
    done
    

    所有 pdf 扫描文件将保留在文件夹中,其他文件将移动到另一个文件夹。

    • 6
  2. Best Answer
    sudodus
    2018-11-20T12:59:41+08:002018-11-20T12:59:41+08:00

    脚本

    • 如果pdf文件包含图像(与文本或整个页面一起插入到文档中,“扫描的 pdf”),则该文件通常(可能总是)包含字符串/Image/.

    • 以同样的方式,您可以搜索字符串/Text以判断 pdf 文件是否包含文本(未扫描)。

    我制作了 shellscript pdf-text-or-image,在大多数情况下它可能适用于您的文件。shellscript在文件/Image/中查找文本字符串。/Textpdf

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

    使 shellscript 可执行,

    chmod ugo+x pdf-text-or-image
    

    将目录更改为您拥有pdf文件的位置并运行 shellscript。

    识别的文件被移动到以下子目录

    • scanned
    • text
    • s-and-t(对于同时包含 [扫描?] 图像和文本内容的文档)

    未识别的文件对象“UFO”保留在当前目录中。

    测试

    我用你的两个文件AR-G1002.pdf和AR-G1003.pdf, 和一些自己的pdf文件(我使用 Libre Office Impress 创建的)测试了 shellscript。

    $ ./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
    

    让我们希望

    • 你的文件集中没有不明飞行物
    • 关于文本与扫描/图像的排序是正确的
    • 4
  3. Tomáš Zato - Reinstate Monica
    2018-11-20T13:50:00+08:002018-11-20T13:50:00+08:00

    如果这更多是关于实际检测 PDF是否是通过扫描创建的,而不是pdf 具有图像而不是文本,那么您可能需要深入研究文件的元数据,而不仅仅是内容。

    一般来说,对于我可以在我的计算机上找到的文件和您的测试文件,以下是正确的:

    • 扫描文件的字符数少于 1000 个字符/页,而非扫描文件的字符数总是超过 1000 个字符/页
    • 多个独立的扫描文件将“Canon”列为 PDF 创建者,可能引用了 Canon 扫描仪软件
    • 以“Microsoft Word”作为创建者的 PDF 可能不会被扫描,因为它们是单词导出。但是有人可以扫描到word,然后导出为PDF——有些人的工作流程很奇怪。

    我目前使用的是 Windows,所以我使用node.js了以下示例:

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

    要运行它,你需要安装 Node.js(应该是一个命令),你还需要调用:

    npm install mz pdf-parse
    

    用法:

    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
    

    这个例子不被认为是完成的解决方案,但是通过debug标志,您可以深入了解文件的元信息:

    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
    

    我编写的简单函数在我可以在我的计算机上找到的文档(包括您的示例)上取得了 100% 的成功。我根据运行程序之前的状态为文件命名,以便查看结果是否正确。

    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
    

    您可以使用调试模式和一点点编程来极大地改善您的结果。您可以将程序的输出传递给其他程序,每行始终有一个完整路径。

    • 2
  4. Johannes Filter
    2020-04-11T14:00:32+08:002020-04-11T14:00:32+08:00

    我创建了一个脚本来检测 PDF 是否为 OCRd。主要思想:在 OCRd PDF 中,文本是不可见的。

    测试给定 PDF ( f1) 是否为 OCRd 的算法:

    1. f1创建记为的副本f2
    2. 删除所有文本f2
    3. 为所有(或仅几个)页面创建图像 (PNG)f1和f2
    4. f1f1如果和的所有图像都相同,则为 OCRd f2。

    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
    
    • 2
  5. Elijah
    2021-01-08T15:45:19+08:002021-01-08T15:45:19+08:00

    据我所知,没有万无一失的方法,但有一些策略。

    pdf 可能嵌入了一些文本,但这可能不是您要查找的文本。例如,一些出版公司,例如 Jstor,即使在 pdf 没有 ocred 的情况下,也会在 pdf 上放置一些与版权相关的文本信息。

    因此,一个好的策略是将 pdf 提供给 pdf 到 txt 转换器并计算字数。如果这个数字太低(完全主观的指标),那么可以合理地预期它没有 ocr。

    下面我们有一个 bash one 衬垫,它为几个文件模拟了这一点(需要并行和 poppler):

    find path/to/files/ -name "*.pdf" | parallel --progress -P3 pdftotext {} - | wc -w >> file.txt
    

    这将计算您目录中每个 pdf 文件的字数。然后,您可以过滤下面的内容,例如 100 个单词,然后将其提供给脚本,例如ocrmypdf对它们进行 ocr。

    • 2
  6. ichabod
    2018-11-20T06:55:40+08:002018-11-20T06:55:40+08:00

    如果文档集合的扫描文档没有添加带有光学字符识别 (OCR) 的文本,Hobbyist 提供了一个很好的解决方案。如果这是可能的,您可能需要编写一些脚本来读取输出pdfinfo -meta并检查用于创建文件的工具,或者使用使用 Python 库之一来检查它们的 Python 例程。使用类似的工具搜索文本strings是不可靠的,因为 PDF 内容可以被压缩。并且检查创建工具也不是万无一失的,因为 PDF 页面可以合并;我经常将 PDF 文本文档与扫描的图像结合起来,以便将它们放在一起。

    很抱歉,我无法提供具体建议。我已经有一段时间没有研究 PDF 的内部结构了,但是根据您的要求有多严格,您可能想知道它有点复杂。祝你好运!

    • 1
  7. swapedoc
    2018-11-20T04:32:11+08:002018-11-20T04:32:11+08:00

    我能想到的2种方法:

    1. 使用选择文本工具:如果您使用的是扫描的 PDF,则无法选择文本,而是会出现一个框。您可以使用此事实来创建脚本。我知道在 C++ QT 中有一种方法,但在 Linux 中不确定。

    2. 在文件中搜索单词:在非扫描的 PDF 中,您的搜索将有效,但在扫描的文件中无效。您只需要找到所有 PDF 共有的一些单词,或者我宁愿说在所有 PDF 中搜索字母“e”。它具有最高的频率分布,因此您很可能会在所有包含文本的文档中找到它(除非它的gadsby)

    例如

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

    使用任何文本处理工具

    • 0

相关问题

  • 如何从命令行仅安装安全更新?关于如何管理更新的一些提示

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve