按行将 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 模型训练)的主要内容,如果未能解决你的问题,请参考以下文章