当前位置: 首页 > 知识库问答 >
问题:

使用Apache PDFBox从PDF文档中删除OCR文本

班言
2023-03-14

系统中的一些PDF文档是通过扫描创建的,其中包括OCR文本。然而,OCR没有正确执行(西里尔语和拉丁语字符混淆),尽管文档看起来可以搜索,但该信息完全不正确,无法使用。

在Adobe Acrobat Reader DC(或GoogleChrome)中查看PDF文档时,它会正确显示,但在使用PDF. js呈现文档的网页上,OCR文本会显示在前面,而不是原始文本的扫描图形呈现。

这个想法是通过从PDF文档中删除OCR文本来“修复”这些文档,同时保留原始文本的扫描图形呈现。

为此,我使用ApachePDFBOx2.0.11来检查PDF文档的内容。以下代码片段打印出PDF文档中包含的整个文本,在本例中,整个文本与OCR文本完全相同:

PDDocument document = PDDocument.load(new File("D:/input.pdf"));
PDFTextStripper stripper = new PDFTextStripper();
stripper.setStartPage(1);
stripper.setEndPage(document.getNumberOfPages());
String sText = stripper.getText(document);
System.out.println(sText);
document.close();

然后我使用了PDFBox提供的示例类RemoveAllText,希望从PDF文档中删除OCR文本。不幸的是,它不仅删除了OCR文本,还删除了原始扫描文本的图形表示。检查PDF文档中的文本元素并将其删除的方法如下所示:

private static List<Object> createTokensWithoutText(PDContentStream contentStream) throws IOException
{
    PDFStreamParser parser = new PDFStreamParser(contentStream);
    Object token = parser.parseNextToken();
    List<Object> newTokens = new ArrayList<Object>();
    while (token != null)
    {
        if (token instanceof Operator)
        {
            Operator op = (Operator) token;
            if ("TJ".equals(op.getName()) || "Tj".equals(op.getName()) ||
                "'".equals(op.getName()) || "\"".equals(op.getName()))
            {
                // remove the one argument to this operator
                newTokens.remove(newTokens.size() - 1);

                token = parser.parseNextToken();
                continue;
            }
        }
        newTokens.add(token);
        token = parser.parseNextToken();
    }
    return newTokens;
}

我假设应该以某种方式更改此方法(仅删除文本而不是删除其图形表示),但我不知道如何做到这一点。

以下是RemoveAllText之前的PDF文档示例,以及RemoveAllText之后的PDF文档示例。

共有1个答案

滕无尘
2023-03-14

从PDFBox示例复制的createTokensWithoutTexthtml" target="_blank">代码中确实存在错误。但是,这个例子从扫描的PDF中删除所有文本的原因是,扫描仪已经从图像中删除了字母,为它们创建了特殊字体,并使用这些字体再次将它们绘制为文本,所以这个例子只是做了它的本意。

虽然显示运算符Tj'、和Tj的文本实际上只有一个参数,“有三个:

awacstring”-移动到下一行并显示文本字符串,使用aw作为单词间距,ac作为字符间距(在文本状态下设置相应的参数)。aw和ac应为以无标度文本空间单位表示的数字。

(ISO 32000-1表109-文本显示运算符)

因此,如果流中有一个“操作,createTokensWithoutText只删除字符串参数和运算符,而保留数值参数aw和ac。这反过来会导致newTokens中以下指令的一组无效参数。

这里的OCR软件并不是简单地在图像中的字形前面或后面添加不可见字符,以提供文本提取功能(这是一种非常常见的方法)。相反,它实际上是从图像中的字形创建特殊字体,从图像中删除字形,并在图像前面清晰地绘制它们。

因此,剩余的图像只包含一些软件没有与任何字形相关联的污垢。

临时字体包含如下字形:

如您所见,字体甚至包含同一个已识别字母的多个字形,例如9、13和15中的“H”。

这种方法的优点是可以更容易地操作PDF,可以编辑文本块。

但不幸的是,OCR软件似乎只知道拉丁字符和阿拉伯数字,尤其是不知道西里尔字母。因此,它将西里尔字母符号指定给最相似的拉丁字符或阿拉伯数字。

这当然会使文本提取变得毫无意义。此外,一些观众使用一些标准字体而不是临时字体中的字形来显示分配的拉丁字符,特别是在标记文本时,这样显示的文本也没有意义。

因此,您应该使用OCR再次扫描,或者将PDF导出为图像,并仅从这些图像构建新的PDF。

 类似资料:
  • 问题内容: 我正在尝试从猫鼬文档中存储的集合中删除一项。我的文档如下所示: 我想删除SKU为12的金鱼。我正在执行以下操作: 当我这样做时,出现错误“ TypeError:无法读取未定义的属性’等于’”。我不明白为什么。 问题答案: 您需要,然后打个电话。用于顶级文档

  • 链接到pdf 当我尝试从上面的pdf中提取文本时,我得到了在evince viewer中不可见的文本和可见的文本的混合。此外,一些所需的文本缺少查看器中没有缺少的字符,例如,“FALCONS”中的“S”和许多缺少的“½”字符。我认为这是由于不可见文本的干扰,因为在查看器中突出显示pdf时,可以看到不可见文本与可见文本重叠。 有没有办法去掉不可见的文字?还是有别的解决办法? 代码: 输出(粗体文本为

  • 问题内容: 我正在使用Mongoose库通过node.js访问MongoDB 有没有办法 从文档中删除密钥 ?即不只是将值设置为null,而是将其删除? 问题答案: 在早期版本中,您需要删除node-mongodb-native驱动程序。每个模型都有一个收集对象,该对象包含node-mongodb- native提供的所有方法。因此,您可以执行以下操作: 从2.0版开始,您可以执行以下操作: 从2

  • 问题内容: 链接到pdf 当我尝试从上面的pdf中提取文本时,我混合了在evince查看器中不可见的文本和可见的文本。此外,某些所需的文本缺少查看器中未缺少的字符,例如“ FALCONS”中的“ S”和许多缺少的“ 1/2”字符。我认为这是由于来自不可见文本的干扰,因为在查看器中突出显示pdf时,可以看到不可见文本与可见文本重叠。 有没有办法删除不可见的文字?还是有其他解决方案? 码: 输出(粗体

  • 我想知道PDF是否是使用OCR从扫描文档创建的。 为了使扫描文档中的文本可以选择,我猜相同的文本是使用透明颜色、特殊字体。。。 我正在使用pdfbox,我查看了字体、颜色和许多其他属性,没有发现任何特殊之处。

  • 使用QPDF,您可以简单地从PDF文件中删除限制/加密,如下所示: 我想用Java中的PDFBox做同样的事情: 我已经用尝试过了,但是我不知道所有者密码是什么。QPDF是如何做到这一点的? 示例文档: https://issues.apache.org/jira/secure/attachment/12514714/in.pdf