按行将 PDF 拆分为图像(OCR 模型训练)

Posted

技术标签:

【中文标题】按行将 PDF 拆分为图像(OCR 模型训练)【英文标题】:Split PDF into Images by Line (OCR Model Training) 【发布时间】:2020-06-27 02:45:37 【问题描述】:

我有大量包含我想要 OCR 的扫描文本的 PDF。

没有任何商业(Abby、PhantomPDF、Acrobat Pro)、服务(Google Vision API)或开源(使用 tesseract、kraken 的预训练模型)工具能够以足够准确的方式对文本进行 OCR。

我有一些原始形式的 PDF(文本完好无损),这意味着我有相当数量的准确、真实的训练数据,在字体、页面结构等方面有大量重叠。

似乎每种训练自己的 OCR 模型的方法都需要逐行设置训练数据,这意味着我需要将训练 PDF 中数百页的每一行剪切成单独的图像(然后我可以只需将训练 PDF 中的文本逐行拆分,即可为 tesseract 或 kraken 创建相应的 gt.txt 文件。

我使用工具按页面拆分 PDF 并将每个页面转换/保存为图像文件,但我无法找到一种方法来自动逐行执行相同的操作。但是,R 的pdftools 使得获取每条线的 y 坐标似乎是可能的......

pdftools::pdf_data(pdf_path)[[3]][1:4, ]
#>   width height   x  y space     text
#> 1    39     17 245 44  TRUE    Table
#> 2    13     17 288 44  TRUE       of
#> 3    61     17 305 44 FALSE Contents
#> 4    41     11  72 74 FALSE Overview

...但我不清楚如何调整它以匹配任何 PDF 到图像例程的分辨率缩放。

说了这么多……

是否有工具可以做到这一点?

如果没有,我应该朝哪个方向发展?

Magick 似乎完全有能力做到这一点(只要我了解如何导航像素),但这并不能解决如何将 y 坐标从 pdftools 之类的东西转换为像素位置的问题在使用 DPI 参数生成的图像中(如每个?PDF 到图像的转换工具)。

编辑#1:

事实证明,坐标是基于 PDF“对象”位置的,这并不一定意味着应该在同一行(并且在视觉上是)的文本总是如此反映。应该在同一行上的文本可能会偏离几个像素。

下一个最好的方法是在每个对象周围裁剪框。在 R 中,这可以解决问题:

build_training_data <- function(pdf_paths, out_path = "training-data") 
  out_path_mold <- "%s/%s-%d-%d.%s"

  for (pdf_path in pdf_paths) 
    prefix <- sub(".pdf", "", basename(pdf_path), fixed = TRUE)

    pdf_data <- pdftools::pdf_data(pdf_path)
    pdf_text <- pdftools::pdf_text(pdf_path)
    pdf_heights <- pdftools::pdf_pagesize(pdf_path)$height

    for (i_page in seq_along(pdf_data)) 
      page_text <- pdf_text[[i_page]]
      line_text <- strsplit(page_text, "\n")[[1L]]

      page_image <- magick::image_read_pdf(pdf_path, pages = i_page)
      image_stats <- magick::image_info(page_image)

      scale_by <- image_stats$height / pdf_heights[[i_page]]

      page_data <- pdf_data[[i_page]]

      for (j_object in seq_len(nrow(page_data))) 
        cat(sprintf("\r- year: %s, page: %d, object: %d        ",
                    prefix, i_page, j_object))
        image_path <- sprintf(out_path_mold, prefix, i_page, j_object)
        text_path <- sprintf(out_path_mold, prefix, i_page, j_object)

        geom <- magick::geometry_area(
          height = page_data$height[[j_object]] * scale_by * 1.2,
          width = page_data$width[[j_object]] * scale_by * 1.1,
          x_off = page_data$x[[j_object]] * scale_by,
          y_off = page_data$y[[j_object]] * scale_by
        )

        line_image <- magick::image_crop(page_image, geom)

        magick::image_write(line_image, format = "png", 
                            path = image_path)

        writeLines(page_data$text[[j_object]], text_path)
      

    

  


这绝对不是最优的。

【问题讨论】:

【参考方案1】:

索尔福德大学设有模式识别和图像分析 (PRImA) 研究实验室。它是他们计算机、科学与工程学院的一部分。他们创建了一些名为 Aletheia 的软件,旨在帮助从图像中创建真实文本。这些可用于训练 Tesseract 版本 3 或 4。

https://www.primaresearch.org/tools/Aletheia

【讨论】:

以上是关于按行将 PDF 拆分为图像(OCR 模型训练)的主要内容,如果未能解决你的问题,请参考以下文章

CNN+LSTM OCR 模型无法正确预测“是”

为 CNN 模型实现交叉验证

按组迭代回归 ML 模型

将图像数组和标签数据帧拆分为训练、测试和验证集

OCR技术系列之三大批量生成文字训练集

阿里50亿参数AI画画模型火了!将图像拆分再自由重组,达摩院副院长率队打造...