Разделить PDF на изображения построчно (обучение модели OCR) - PullRequest
0 голосов
/ 16 марта 2020

У меня есть большая коллекция PDF-файлов, содержащих отсканированный текст, который я хотел бы использовать для распознавания текста.

Нет рекламы (Abby, PhantomPDF, Acrobat Pro), службы (Google Vision API) или открытого источника ( Предварительно обученные модели, использующие инструмент tesseract, kraken), смогли распознать текст достаточно точно.

У меня есть несколько PDF-файлов в их первоначальном виде (с неповрежденным текстом), что означает, что у меня есть разумное количество точных, основополагающих данных обучения с огромным совпадением шрифтов, структуры страницы и т. д. c.

Кажется, что каждый метод обучения вашей собственной модели OCR требует настройки данных обучения это означает, что мне нужно разрезать каждую строку из сотен страниц обучающих PDF-файлов на отдельные изображения (тогда я могу просто разбить текст в обучающих PDF-файлах по строкам, чтобы создать соответствующие файлы gt.txt для tesseract или kraken ).

Я использовал инструменты для разделения PDF-файлов по страницам и преобразования / сохранения каждой страницы в файл изображения, но мне не удалось найти способ Tomate делает то же самое построчно. Но, из-за 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 в изображение).

Edit # 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)
      }

    }

  }

}

Это определенно не оптимально.

...