### 检查PDF是否已进行OCR处理或PDF是否可搜索为真

有没有Python的方法来识别PDF是否已经进行OCR处理(文本质量差)还是一个可搜索的PDF(文本质量完美)?

使用PDF的元数据

import pprint
import PyPDF2

def get_doc_info(path):
    pp  = pprint.PrettyPrinter(indent =4)
    pdf_file = PyPDF2.PdfFileReader(path, 'rb')
    doc_info = pdf_file.getDocumentInfo()
    pp.pprint(doc_info)

我发现:

result = get_doc_info(PDF_SEARCHABLE_HAS_BEEN_OCRD.pdf)
{   '/Author': 'NAPS2',
    '/CreationDate': "D:20200701104101+02'00'",
    '/Creator': 'NAPS2',
    '/Keywords': '',
    '/ModDate': "D:20200701104101+02'00'",
    '/Producer': 'PDFsharp 1.50.4589 (www.pdfsharp.com)'}
result = get_doc_info(PDF_SEARCHABLE_TRUE.pdf)
{   '/CreationDate': 'D:20210802122000Z',
    '/Creator': 'Quadient CXM AG~Inspire~14.3.49.7',
    '/Producer': ''}

我可以使用PDF元数据中的Creator来检查PDF的类型(真正的PDF还是OCR PDF)吗?

还有其他使用Python的方法吗?

如果这个问题没有解决方案,我如何使用深度学习/机器学习来检测PDF可搜索的类型(真或OCR)?

这是一个视频,帮助理解真PDF和OCR PDF之间的区别:https://www.youtube.com/watch?v=xs8KQbxsMcw


回答:

不久前我遇到了同样的问题!

我开发了(基于某个我无法回想的SO帖子)这个函数:

def get_scanned_pages_percentage(filepath: str) -> float:
    """    INPUT: PDF文件的路径    OUTPUT: OCR处理的包含文本的页面百分比"""
    total_pages = 0
    total_scanned_pages = 0
    with fitz.open(filepath) as doc:
        for page in doc:
            text = page.getText().strip()
            if len(text) == 0:
                # 忽略“空”页面
                continue
            total_pages += 1
            pix1 = page.getPixmap(alpha=False)  # 将页面渲染为图像
            remove_all_text(doc, page)
            pix2 = page.getPixmap(alpha=False)
            img1 = pix1.getImageData("png")
            img2 = pix2.getImageData("png")
            if img1 == img2:
                # print(f"{page.number} was scanned or has no text")
                if len(text) > 0:
                    # print(f"\tHas text of length {len(text):,} characters")
                    total_scanned_pages += 1
            else:
                pass
    if total_pages == 0:
        return 0
    return (total_scanned_pages / total_pages) * 100

这个函数如果PDF是包含OCR处理文本的图像,将返回100(或接近100),如果是原生数字PDF,则返回0。

删除所有文本:

def remove_all_text(doc, page):
    """从PDF文档页面(元数据)中删除所有文本"""
    page.cleanContents()  # 清理页面外观命令的语法
    # 清理后的命令源(字节对象)的xref
    xref = page.getContents()[0]
    cont = doc.xrefStream(xref)  # 读取它
    # 元数据以字节形式存储,它提取为字节。然后搜索引用文本的标签并删除它。
    ba_cont = bytearray(cont)  # 可修改版本
    pos = 0
    changed = False  # 指示更改的开关
    while pos < len(cont) - 1:
        pos = ba_cont.find(b"BT\n", pos)  # 开始文本对象
        if pos < 0:
            break  # 未(更多)找到
        pos2 = ba_cont.find(b"ET\n", pos)  # 结束文本对象
        if pos2 <= pos:
            break  # PDF页面定义中的重大错误!
        ba_cont[pos: pos2 + 2] = b""  # 删除文本对象
        changed = True
    if changed:  # 我们确实删除了一些文本
        doc.updateStream(xref, ba_cont)  # 写回不含文本的命令流

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注