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

文本位置边界框PDFBox

韦阳辉
2023-03-14

下面是我的函数,它从glyph空间到用户空间进行计算

@Override 
protected void processTextPosition(TextPosition text) {
    PDFont font = pos.getFont();
    
    BoundingBox bbox = font.getBoundingBox();
    
    Rectangle2D.Float rect = new Rectangle2D.Float(bbox.getLowerLeftX(), bbox.getUpperRightY(), 
            bbox.getWidth(), bbox.getHeight());
    
    AffineTransform at = pos.getTextMatrix().createAffineTransform();
    
    if (font instanceof PDType3Font) {
        at.concatenate(font.getFontMatrix().createAffineTransform());
    } else {
        at.scale(1 / 1000f, 1 / 1000f);
    }
    Shape shape = at.createTransformedShape(rect);
    rectangles.add(fillBBox(text));
    
            
    super.processTextPosition(text);
}

下面是绘制提取的矩形的函数:

private void drawBoundingBoxes() throws IOException {
    
    String fileNameOut = path.substring(0, path.lastIndexOf(".")) + "_OUT.pdf";
    log.info("Drawing Bounding Boxes for TextPositions");
    
    PDPageContentStream contentStream = new PDPageContentStream(document, 
            document.getPage(document.getNumberOfPages()-1),
            PDPageContentStream.AppendMode.APPEND, false , true );
    contentStream.setLineWidth(1f);
    contentStream.setStrokingColor(Color.RED);
    
    try{
        for (Shape p : rectangles) {
            p = all.get(0);
        double[] coords = new double[6];
        GeneralPath g = new GeneralPath(p.getBounds2D());
        for (PathIterator pi = g.getPathIterator(null);
             !pi.isDone();
             pi.next()) {
            System.out.println(Arrays.toString(coords));
            switch (pi.currentSegment(coords)) {
            case PathIterator.SEG_MOVETO:
                System.out.println("move to");
                contentStream.moveTo ((float)coords[0], (float) coords[1]);
                break;
                
            case PathIterator.SEG_LINETO:
                System.out.println("line to");
                contentStream.lineTo ((float)coords[0], (float) coords[1]);
                break;
                
            case PathIterator.SEG_CUBICTO:
                System.out.println("cubc to");
                contentStream.curveTo((float)coords[0], (float) coords[1],
                        (float)coords[2], (float) coords[3], 
                        (float)coords[4],(float) coords[5]);
                break;
                
            case PathIterator.SEG_CLOSE:
                System.out.println("close");
                contentStream.closeAndStroke();
                break;
            default:
                System.out.println("no shatt");
                break;
            }
            
        }
    
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        contentStream.close();
        document.save(new File(fileNameOut));
    }
}

我不知道我做错了什么。有什么想法吗?

共有1个答案

白越
2023-03-14

D先生,

我测试了你的代码,唯一需要做的修改就是反转Y轴。之所以需要这样做,是因为PDF用户空间的原点位于左下角,而Java 2D用户空间的原点位于左上角。

8.3.2.3用户空间

用户空间坐标系应初始化为文件每页的默认状态。页面字典中的CropBox条目应指定与预期输出介质(显示窗口或打印页面)可见区域相对应的用户空间矩形。正x轴水平向右延伸,正y轴垂直向上延伸,如在标准数学实践中(可通过页面字典中的旋转条目进行更改)。沿x轴和y轴的单位长度由页面字典中的UserUnit条目(PDF 1.6)设置(见表30)。如果该条目不存在或不受支持,则使用默认值1⁄72英寸。该坐标系称为默认用户空间[2]

@Override 
protected void processTextPosition(TextPosition text) {
    try {
        PDFont font = pos.getFont();

        BoundingBox bbox = font.getBoundingBox();

        Rectangle2D.Float rect = new Rectangle2D.Float(bbox.getLowerLeftX(), bbox.getUpperRightY(),
                    bbox.getWidth(), bbox.getHeight());

        AffineTransform at = pos.getTextMatrix().createAffineTransform();

        if (font instanceof PDType3Font) {
            at.concatenate(font.getFontMatrix().createAffineTransform());
        } else {
            at.scale(1 / 1000f, 1 / 1000f);
        }

        Shape shape = at.createTransformedShape(rect);

        // Invert Y axis
        Rectangle2D bounds = shape.getBounds2D();
        bounds.setRect(bounds.getX(), bounds.getY() - bounds.getHeight(), bounds.getWidth(), bounds.getHeight());

        rectangles.add(bounds);

        super.processTextPosition(text);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

>

  • Java2D API概念:坐标

    文件管理.便携式文件格式.第1部分:PDF 1.7,PDF 32000-1:2008,第8.3节:坐标系,第115页

  •  类似资料:
    • 正如评论所说,这项工作很难,所以我想一步一步地解决它,看看它的局限性。首先,我将集中在下面的第一个问题上。 起源: 我想替换PDF文件中的文本以进行翻译,例如,将英文PDF转换为中文PDF。 我的解决方案是: 查找位置为矩形的所有文本 具体来说,我实现了IEventListener接口来获取渲染信息,并使用此渲染信息来查找带有位置矩形的文本。 但我遇到了一些问题: 使用“渲染信息”,我无法获得文本

    • 我如何用材料组件做到这一点? 我不想在边框之间有这样的标签:(当你有多个填充字段时,这看起来不再好看了,在我看来,所有中断的边框都很紧张)

    • 在前面的一些章节中,我们介绍了诸多用于图像分类的模型。在图像分类任务里,我们假设图像里只有一个主体目标,并关注如何识别该目标的类别。然而,很多时候图像里有多个我们感兴趣的目标,我们不仅想知道它们的类别,还想得到它们在图像中的具体位置。在计算机视觉里,我们将这类任务称为目标检测(object detection)或物体检测。 目标检测在多个领域中被广泛使用。例如,在无人驾驶里,我们需要通过识别拍摄到

    • 问题内容: 我有一个二维的numpy数组看起来像 我想在上面显示的1上方创建像蒙版这样的边界框。例如,它应该看起来像这样 我如何轻松做到这一点?另外,如果存在其他编号(例如2,3等),但我想忽略它们,而该组主要是2,该怎么办。 问题答案: 在组件标签方面,我们必须让生活变得轻松。我们可以用来标记数组中的不同组件,并获得相应的切片,在这种情况下,可以使用它们来将值设置为: 如果我们尝试提出的示例:

    • 问题内容: 我有两个边界框的两个坐标,其中一个是地面坐标,另一个是我工作的结果。我想根据地雷来评估我的准确性。所以我问是否有人有任何建议 边框详细信息以这种格式保存 问题答案: 编辑:我已更正其他用户指出的错误。 我假设您正在检测某些对象,并且正在围绕它绘制一个边界框。这属于对象检测的广泛研究/研究领域。评估精度的最佳方法是计算并集交集。这是从PASCAL VOC挑战中获得的,这里。请参阅此处的视

    • 我需要将matplotlib图形保存到pdf。我遵循Matplotlib howto上的说明,只是不显示结果,而是将其保存为pdf。奇怪的是,pdf画布不受画布大小的影响。相反,保存为png可以在放大的画布上正常工作。 pdf图像的截屏 更新 对标题和轴标记执行此操作,但如果图例位于框架外部,则忽略图例,如下图所示。请注意,我将图例放置在图形的右侧。