我正在開發一種算法從閱讀順序中的PDF文件中提取文本和圖像。我爲此使用iText java,基本上我的算法的工作原理如下。iText提取文本塊的錯誤位置
- 使用iText提取頁面中每個文本塊的座標。
- 使用提取的座標創建矩形對象。在這一步之後,我們有一大堆代表頁面中實際文本塊的矩形對象。
- 將矩形分組爲更大的文本塊,這些文本塊將對應於pdf頁面中的實際列。
- 按Y對文本塊進行排序,然後輸入X
- 將
locationTextExtractionStrategy
逐個應用於文本塊。
這種方法使得我的PDF文件的結果大約有80%或略多一些,而且中等到複雜的佈局。我知道,要獲得100%的準確度幾乎是不可能的,因爲PDF文件不會按照閱讀順序存儲信息。
我想要做的是提高我的準確性,但問題是iText阻止我這樣做。我在iText中發現了一個問題。它有時會提取文本塊的錯誤位置,這使得我的算法不正確。以下圖片就是一個很好的例子。
你可以看到,在實際的PDF頁面有列之間明顯的差距。但是由此產生的矩形包含了一些有缺陷的矩形,它們之間的差距阻礙了我識別正確的列。
以下是我用來提取文本塊位置的代碼。
package com.InteliText.Extract;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.LineSegment;
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import com.itextpdf.text.pdf.parser.Vector;
/*
* THIS CLASS ACT AS THE TEXT EXTRACTOR FOR THE PREPROCESSOR
*/
public class PreProcessorStrategy extends SimpleTextExtractionStrategy{
private StringBuilder result = new StringBuilder();
private ArrayList<Double> fontSizes = new ArrayList<Double>();
private ArrayList<Double> lineSpaces = new ArrayList<Double>();
private ArrayList<TextSegment> textSegments = new ArrayList<TextSegment>();
Vector previousBaseLine = null;
@Override
public void beginTextBlock() {
// TODO Auto-generated method stub
}
@Override
public void endTextBlock() {
// TODO Auto-generated method stub
}
@Override
public void renderImage(ImageRenderInfo arg0) {
// TODO Auto-generated method stub
}
@Override
public void renderText(TextRenderInfo renderInfo) {
//This code assumes that if the baseline changes then we're on a newline
Vector curBaseline = renderInfo.getBaseline().getStartPoint();
Vector topRight = renderInfo.getAscentLine().getEndPoint();
//System.out.println(renderInfo.getText()+"\t"+curBaseline.get(0)+"\t"+topRight.get(0));
if(curBaseline.get(1) < 800 && curBaseline.get(1) > 50) {
// Chunk of text as a rectangle
Rectangle rect = new Rectangle(curBaseline.get(0), curBaseline.get(1), topRight.get(0), topRight.get(1));
double curFontSize = rect.getHeight();
fontSizes.add(curFontSize);
String text = renderInfo.getText();
boolean isBullet = text.contains("•");
if(!(text.equals(" ") || text.equals(" ") || text.equals(" ")) && !isBullet) {
double endX = topRight.get(0);
if(text.endsWith(" "))
endX -= 8;
textSegments.add(new TextSegment(curBaseline.get(0),endX,curBaseline.get(1),topRight.get(1),renderInfo.getText(),curFontSize));
}
result.append(renderInfo.getText());
}
previousBaseLine = topRight;
}
@Override
public String getResultantText() {
// TODO Auto-generated method stub
return result.toString();
}
public ArrayList<TextSegment> getResultantTextSegments() {
return this.textSegments;
}
我使用產生textSegments
ArrayList中通過查看存儲在這些textSegments座標以創建矩形對象。我懷疑這可能是iText中的一個錯誤。
正如您目前所看到的,如果該文本塊的內容以空白結尾,我會縮小文本塊的大小。但這是一個臨時性的修復,我不想這樣做,因爲它縮小了正確的文本塊。
那麼有沒有這方面的工作?或者,如果這是我的代碼中的問題,請幫我解決這個問題..
它看起來像文本顯示操作顯示尾部空格,這是您的框的一部分,並超出列邊界。 – mkl