PDFBox:如何区分透明OCR文本与非透明普通文本
基于PDFBox区分透明OCR文本与普通非透明文本的实现方案
核心判断依据
OCR工具生成的叠加在扫描图片上的可检索文本,通常会设置完全透明的渲染属性(填充色/描边色的alpha值为0),仅用于检索不用于显示;而普通可见文本的alpha值默认为1,这是两类文本最核心的区分特征。
具体实现步骤
- 自定义文本提取器,继承PDFBox的
PDFTextStripper类,重写processTextPosition文本处理回调方法,获取文本对应的图形状态参数 - 校验文本透明度:通过当前图形状态的
getNonStrokingColor().getAlpha()方法获取填充色透明度,仅保留alpha值为0的文本;部分场景下可额外校验getStrokingColor().getAlpha()描边色透明度,避免漏判 - 增加区域校验逻辑:提前识别当前页面所有图片的边界框,仅保留边界框完全落在某张图片范围内的透明文本,过滤图片外的无关普通文本
- 收集符合上述两个条件的文本,即为你需要的OCR生成的透明目标文本
核心代码示例
import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.TextPosition; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import java.io.IOException; import java.util.List; public class OCRTransparentTextExtractor extends PDFTextStripper { // 存储当前页面所有图片的边界框信息 private List<PDRectangle> pageImageBounds; public OCRTransparentTextExtractor() throws IOException { super(); } // 传入当前页面识别到的所有图片边界框 public void setPageImageBounds(List<PDRectangle> pageImageBounds) { this.pageImageBounds = pageImageBounds; } @Override protected void processTextPosition(TextPosition text) { // 校验文本是否完全透明 float fillAlpha = getGraphicsState().getNonStrokingColor().getAlpha(); float strokeAlpha = getGraphicsState().getStrokingColor().getAlpha(); if (fillAlpha != 0 && strokeAlpha != 0) { return; } // 校验文本是否落在图片区域内 PDRectangle textBound = new PDRectangle( text.getXDirAdj(), text.getYDirAdj() - text.getHeightDir(), text.getWidthDirAdj(), text.getHeightDir() ); for (PDRectangle imageBound : pageImageBounds) { if (imageBound.contains(textBound)) { super.processTextPosition(text); break; } } } }
场景适配说明
针对你提到的测试文件,上述逻辑可以实现需求:
- 第4页图片下方的普通文本alpha值为1,且不在图片边界框内,会被直接过滤
- 第2、3、12页位于图片后方的OCR透明文本,同时满足透明度为0、处于图片区域两个条件,会被正常提取
内容的提问来源于stack exchange,提问作者Szőke Attila
相关产品推荐
相关产品推荐

