Тессеракт "Ошибка в pixCreateNoInit: сбой pix_malloc для данных"

Пытаясь запустить эту функцию внутри функции, основанной на этом, однако, поскольку xPDF может конвертировать PDF-файлы в PNG, я пропустил шаг преобразования ImageMagick, а также неисправную логику в процессе функции (i), поскольку pdftopng требует root name и в данном случае это "ocrbook-000001.png", который выдает ошибку при поиске PNG имени исходного файла PDF.

Моя проблема сейчас в том, чтобы заставить Tesseract сделать что-нибудь с моими файлами PNG. Я получаю ошибку:

Tesseract Open Source OCR Engine v3.05.01 with Leptonica
Error in pixCreateNoInit: pix_malloc fail for data
Error in pixCreate: pixd not made
Error in pixReadStreamPng: pix not made
Error in pixReadStream: png: no pix returned
Error in pixRead: pix not read
Error during processing.

Вот мой код:

lapply(myfiles, function(i){

shell(shQuote(paste0("pdftopng -f 1 -l 10 -r 600 ", i, " ocrbook")))
mypngs <- list.files(path = dest, pattern = "png", full.names = TRUE)
    lapply(mypngs, function(z){
    shell(shQuote(paste0("tesseract ", z, " out")))
    file.remove(paste0(z))
    })
})

2 ответа

Решение

По-видимому, проблема заключалась в том, что DPI было установлено слишком высоким, чтобы Tesseract мог с ним справиться. Изменение параметра PDFtoPNG DPI с 600 на 150, по-видимому, устранило проблему. Кажется, для Tesseract существует максимальное значение DPI для понимания и понимания того, что делать.

Я также исправил свой код из статического соглашения об именах в более динамичный, который имитирует оригинальные имена файлов.

  dest <- "C:\\users\\YOURNAME\\desktop"

  files <- tools::file_path_sans_ext(list.files(path = dest, pattern = "pdf", full.names = TRUE))
    lapply(files, function(i){
      shell(shQuote(paste0("pdftoppm -f 1 -l 10 -r 150 ", i,".pdf", " ",i)))
      })


  myppms <- tools::file_path_sans_ext(list.files(path = dest, pattern = "ppm", full.names = TRUE))
    lapply(myppms, function(y){
      shell(shQuote(paste0("magick ", y,".ppm"," ",y,".tif")))
      file.remove(paste0(y,".ppm"))
      })

  mytiffs <- tools::file_path_sans_ext(list.files(path = dest, pattern = "tif", full.names = TRUE))
    lapply(mytiffs, function(z){
      shell(shQuote(paste0("tesseract ", z,".tif", " ",z)))
      file.remove(paste0(z,".tif"))
      })

Фон

Похоже, вы уже решили свою проблему. Ура! Я пишу этот ответ, потому что столкнулся с очень похожей проблемой при вызове tesseract из R и хотел поделиться некоторыми обходными путями, которые я придумал, на случай, если кто-то еще наткнется на этот пост и ему понадобятся дополнительные идеи по устранению неполадок.

В моем случае я преобразовывал кучу факсов (около 3000 отдельных pdf-файлов, большинство из них от 1 до 15 страниц) в текст. Я использовал функцию применения, чтобы сделать текст каждого отдельного факса отдельной записью в списке (длина = количество факсов = ~ 3000). Затем факсы были преобразованы в вектор, а затем этот вектор был объединен с вектором имен файлов для создания фрейма данных. Наконец, я записал фрейм данных в файл csv. (См. ниже код, который я использовал).

Проблема заключалась в том, что я продолжал получать ту же строку ошибок, что и вы:

      Tesseract Open Source OCR Engine v3.05.01 with Leptonica
Error in pixCreateNoInit: pix_malloc fail for data
Error in pixCreate: pixd not made
Error in pixReadStreamPng: pix not made
Error in pixReadStream: png: no pix returned
Error in pixRead: pix not read
Error during processing.

Вслед за этой ошибкой:error in FUN(X[[i]], ...) : basic_string::_M_construct null not valid

В чем я думаю проблема

Что было странно для меня, так это то, что я повторно запускал код несколько раз, и всегда это был другой факс, где возникала ошибка. Похоже, это также происходило чаще, когда я пытался сделать что-то еще, что использовало много ОЗУ или ЦП (открытие команд Microsoft и т. д.). Я попытался изменить DPI, как было предложено в первом ответе, и это, похоже, не сработало.

Также было заметно, что во время работы этого кода я регулярно использовал почти 100% ОЗУ и 50% ЦП (на основе диспетчера задач Windows).

Когда я запускал этот процесс (на аналогичной партии из примерно 3000 факсов) на Linux-машине со значительно большим объемом ОЗУ и ЦП, я никогда не сталкивался с этой проблемой.

, похоже, ошибка C++. Я не знаком с С++, но это звучит так, будто это какая-то общая ошибка, которая может указывать на то, что что-то, что должно было быть создано, не было создано.

Исходя из всего этого, я думаю, что проблема в том, что у R заканчивается память, и в ответ каким-то образом память, доступная для некоторых базовых процессов tesseract, отключается. Это означает, что не хватает памяти для преобразования pdf в png и последующего извлечения текста, который вызывает эти ошибки. Это приводит к тому, что текстовый BLOB-объект не создается там, где он ожидается, и завершается ошибка C++:Возможно, что снижение dpi дало вашему процессу достаточно памяти для завершения, но, возможно, основной проблемой была память, а не DPI.

Возможные обходные пути

Итак, я не уверен ни в одном из того, что я только что сказал, но исходя из этого предположения, вот несколько идей, которые я придумал для людей, использующих пакет tesseract в R, которые сталкиваются с похожими проблемами:

  1. Переключитесь с Rstudio на Rgui: это само по себе решило мою проблему. С помощью Rgui я смог завершить весь процесс обработки 3000 факсов без каких-либо ошибок. Rgui также использовал от 100 до 400 МБ вместо 1000+, которые использовал Rstudio, и около 25% ЦП вместо 50%. Помещение R в путь и запуск R из консоли или запуск R в фоновом режиме может еще больше сократить использование памяти.

  2. Закройте все процессы, интенсивно использующие память, на время выполнения кода. Команды Microsoft, видеоконференции, потоковая передача, докер в Windows и подсистема Windows Linux — все это огромные пожиратели памяти.

  3. более низкий DPI. Как было предложено в первом ответе, это также, вероятно, уменьшит использование памяти.

  4. разбить процесс. Я думаю, что запуск моих процессов в пакетах примерно по 500 мог бы также уменьшить объем рабочей памяти, которую R должен занимать перед записью в файл.

Все это быстрые и простые решения, которые можно реализовать в R без необходимости изучения C++ или обновления оборудования. Более надежное решение, вероятно, потребует дополнительной настройки параметров тессеракта, реализации процесса на C++, изменения параметров выделения памяти для R и операционной системы или покупки дополнительной оперативной памяти.

Пример кода

      # Load Libraries
library(tesseract)


dir.create("finished_data")

# Define Functions
ocr2 <- function(pdf_path){
  
  # tell tesseract which language to guess
  eng <- tesseract("eng")
  
  #convert to png first
  #pngfile <- pdftools::pdf_convert(pdf_path, dpi = 300)
 
  # tell tesseract to convert the pdf at pdf_path
   seperated_pages <- tesseract::ocr(pdf_path, engine = eng)
  

  #combine all the pages into one page
  combined_pages <- paste(seperated_pages, collapse = "**new page**")
  
  
  # I delete png files as I go to avoid overfilling the hard drive
  # because work computer has no hard drive space :'(

  png_file_paths <-  list.files(pattern = "png$")
  
  file.remove(png_file_paths)
  
  combined_pages
  
}


# find pdf_paths

fax_file_paths <-  list.files(path="./raw_data", 
                                    pattern = "pdf$",
                                    recursive = TRUE)


#this converts all the pdfs to text using the ocr
faxes <- lapply(paste0("./raw_data/",fax_file_paths), 
                       ocr2)  




fax_table <- data.frame(file_name= fax_file_paths, file_text= unlist(faxes))


write.csv(fax_table, file = paste0("./finished_data/faxes_",format(Sys.Date(),"%b-%d-%Y"), "_test.csv"),row.names = FALSE)

Другие вопросы по тегам