【问题标题】:Retrieve the respective coordinates of all words on the page with itextsharp使用 itextsharp 检索页面上所有单词的各自坐标
【发布时间】:2012-12-05 00:51:06
【问题描述】:

我的目标是检索页面上所有单词的各自坐标,我所做的是

PdfReader reader = new PdfReader("cde.pdf");
TextWithPositionExtractionStategy S = new TextWithPositionExtractionStategy();
PdfTextExtractor.GetTextFromPage(reader,1,S);

Vector curBaseline = renderInfo.GetDescentLine().GetStartPoint();
Vector topRight = renderInfo.GetAscentLine().GetEndPoint();

iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(curBaseline[Vector.I1], curBaseline[Vector.I2], topRight[Vector.I1], topRight[Vector.I2]);
string x1 = curBaseline[Vector.I1].ToString();
string x2 = curBaseline[Vector.I2].ToString();
string x3 = topRight[Vector.I1].ToString();
string x4 = topRight[Vector.I2].ToString();

但是,我得到的是一个字符串的坐标,它包含了一行的所有单词,而不是一个单词。例如pdf的内容是“我是女孩”,我得到的是“的坐标”我是女孩”,但不是“i”“am”“a”“girl”的坐标。如何修改代码以便获得单词坐标。谢谢。

【问题讨论】:

  • 一个词就是一个字符串。向我们准确展示您得到的结果,并将其与您想要的结果进行比较。
  • PDF 中的文本段不一定在单词边界处开始或停止。因此,您将不得不拆分文本段或合并它们。
  • @mkl,谢谢,我知道你说什么,但我不知道该怎么做。你能给我更多帮助吗?

标签: c# itextsharp


【解决方案1】:

(我主要使用 Java 库 iText,而不是 .Net 库 iTextSharp;因此,请忽略这里的一些 Java 主义,一切都应该易于翻译。)

为了使用 iText(Sharp) 提取页面内容,您可以使用解析器包中的类在对您选择的 RenderListener 进行一些预处理后将其提供给您。

在您只对文本感兴趣的上下文中,您最常使用TextExtractionStrategy,它派生自RenderListener,并添加了一个方法getResultantText 从页面中检索聚合文本。

由于 iText 中文本解析的最初意图是实现此用例,因此大多数现有的 RenderListener 示例都是 TextExtractionStrategy 实现,并且只提供文本。

因此,您必须实现自己的 RenderListener,您似乎已经信奉了 TextWithPositionExtractionStategy

就像SimpleTextExtractionStrategy(通过一些关于页面内容操作符的结构的假设来实现)和LocationTextExtractionStrategy(没有相同的假设但稍微复杂一些),你可能想要从一个做出一些假设的实现开始。

因此,就像SimpleTextExtractionStrategy 的情况一样,您在第一个简单的实现中期望转发给您的侦听器的文本呈现事件逐行到达,并且从左到右在同一行上。这样一来,一旦您发现水平间隙或标点,您就知道您当前的单词已经完成并且您可以对其进行处理。

与文本提取策略相比,您不需要StringBuffer 成员来收集结果,而是需要一些“带有位置的单词”结构的列表。此外,您需要一些成员变量来保存您已经为此页面收集但最终无法处理的TextRenderInfo 事件(您可以在多个单独的事件中检索一个单词)。

一旦你(即你的renderText 方法)被调用一个新的TextRenderInfo 对象,你应该像这样操作(伪代码):

if (unprocessedTextRenderInfos not empty)
{
    if (isNewLine // Check this like the simple text extraction strategy checks for hardReturn
     || isGapFromPrevious) // Check this like the simple text extraction strategy checks whether to insert a space
    {
        process(unprocessedTextRenderInfos);
        unprocessedTextRenderInfos.clear();
    }
}

split new TextRenderInfo using its getCharacterRenderInfos() method;
while (characterRenderInfos contain word end)
{
    add characterRenderInfos up to excluding the white space/punctuation to unprocessedTextRenderInfos;
    process(unprocessedTextRenderInfos);
    unprocessedTextRenderInfos.clear();
    remove used render infos from characterRenderInfos;
}
add remaining characterRenderInfos to unprocessedTextRenderInfos;

process(unprocessedTextRenderInfos) 中,您从未处理的TextRenderInfos 中提取您需要的信息;您将单个文本内容连接到一个单词并获取所需的坐标;如果您只想要起始坐标,您可以从第一个未处理的 TextRenderInfos 中获取这些坐标。如果您需要更多数据,还可以使用来自其他 TextRenderInfo 的数据。使用这些数据,您可以填写“带有位置的单词”结构并将其添加到您的结果列表中。

页面处理完成后,你必须再次调用 process(unprocessedTextRenderInfos) 和 unprocessedTextRenderInfos.clear();或者,您可以在 endTextBlock 方法中执行此操作。

完成此操作后,您可能已经准备好实现稍微复杂一些的变体,它对页面内容结构没有相同的假设。 ;)

【讨论】:

  • 您好!我遵循了这个解决方案,并且“几乎”得到了它,除了我正在努力将每个特定单词的坐标(矩形本身)放在初始块的矩形内。是否有任何“简单”的方法来执行此操作?实际上,我正在提取 TextChunk 中的每个单词,并根据实际的 Left、Right 等计算出坐标。我是否以正确的方式做这件事?非常感谢您的解释!
  • @Gonzo345 你考虑过split new TextRenderInfo using its getCharacterRenderInfos() method这一步吗?在该步骤中,您会为每个字形获得一个TextRenderInfo,因此,特别是对于每个字形开始或结束一个单词。如果您已经考虑了这一点,但仍然没有继续前进,请创建一个实际的堆栈溢出问题,提供足够的代码和示例文档来重现该问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多