Как решить MemoryError с помощью библиотеки Python 3.7 pdf2image? - PullRequest
1 голос
/ 06 июня 2019

Я запускаю простое преобразование PDF в изображение с использованием библиотеки Python PDF2Image.Я, конечно, могу понять, что максимальный объем памяти пересекается этой библиотекой, чтобы получить эту ошибку.Но, PDF равен 6,6 МБ (приблизительно), тогда почему бы потребовалось ГБ памяти, чтобы выдать ошибку памяти?

Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pdf2image import convert_from_path
>>> pages = convert_from_path(r'C:\Users\aakashba598\Documents\pwc-annual-report-2017-2018.pdf', 200)
Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Users\aakashba598\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\aakashba598\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\aakashba598\AppData\Local\Programs\Python\Python37-32\lib\subprocess.py", line 1215, in _readerthread
    buffer.append(fh.read())
MemoryError

Кроме того, каково возможное решение этой проблемы??

Обновление: когда я уменьшил параметр dpi из функции convert_from_path , он работает как шарм.Но снимки получаются низкого качества (по понятным причинам).Есть ли способ это исправить?Как пакетное создание изображений и очистка памяти каждый раз.Если есть способ, как это сделать?

Ответы [ 3 ]

3 голосов
/ 06 июня 2019

Преобразование PDF в блоки по 10 страниц каждый раз (1-10,11-20 и т. Д.)

maxPages = pdf2image._page_count(pdf_file)
for page in range(1,maxPages,10) : 
   convert_from_path(pdf_file, dpi=200, first_page=page, last_page = min(page+10-1,maxPages))
1 голос
/ 06 июня 2019

Я немного опоздал, но проблема действительно связана с тем, что 136 страниц заносятся в память.Вы можете сделать три вещи.

  1. Указать формат для преобразованных изображений.

По умолчанию pdf2image использует PPM в качестве формата изображения, он быстрее, но также требуетнамного больше памяти (более 30 МБ на изображение!).Что вы можете сделать, чтобы это исправить, так это использовать более удобный для памяти формат, такой как jpeg или png.

convert_from_path('C:\path\to\your\pdf', fmt='jpeg')

Это, вероятно, решит проблему, но это в основном только из-за сжатия, и в какой-то момент (скажем, PDF + 500 страниц) проблема появится снова.

Использовать выходной каталог

Я бы порекомендовал этот каталог, поскольку он позволяет обрабатывать любые PDF-файлы.Пример на странице README объясняет это хорошо:

import tempfile

with tempfile.TemporaryDirectory() as path:
    images_from_path = convert_from_path('C:\path\to\your\pdf', output_folder=path)

Это временно записывает образ в память вашего компьютера, поэтому вам не нужно удалять его вручную.Обязательно выполните любую необходимую обработку перед выходом из контекста with!

Обрабатывать PDF-файл кусками

pdf2image позволяет определить первую последнюю страницу, которую вы хотите обработать.Это означает, что в вашем случае с PDF на 136 страниц вы можете сделать:

for i in range(0, 136 // 10 + 1):
    convert_from_path('C:\path\to\your\pdf', first=i*10, last=(i+1)*10)
0 голосов
/ 06 июня 2019

Относительно большой PDF-файл израсходует всю вашу память и приведет к остановке процесса (если вы не используете выходную папку) https://github.com/Belval/pdf2image Я думаю, это поможет вам понять.

Решение:Разбить PDF на мелкие части и преобразовать его в изображение.Изображение может быть объединено ...

 from PyPDF2 import PdfFileWriter, PdfFileReader

 inputpdf = PdfFileReader(open("document.pdf", "rb"))

 for i in range(inputpdf.numPages):
     output = PdfFileWriter()
     output.addPage(inputpdf.getPage(i))
     with open("document-page%s.pdf" % i, "wb") as outputStream:
         output.write(outputStream)

разделить многостраничный pdf-файл на несколько pdf-файлов с помощью python?

 import numpy as np
 import PIL

 list_im = ['Test1.jpg', 'Test2.jpg', 'Test3.jpg']
 imgs    = [ PIL.Image.open(i) for i in list_im ]
 # pick the image which is the smallest, and resize the others to match it (can be   arbitrary image shape here)
 min_shape = sorted( [(np.sum(i.size), i.size ) for i in imgs])[0][1]
 imgs_comb = np.hstack( (np.asarray( i.resize(min_shape) ) for i in imgs ) )

 # save that beautiful picture
 imgs_comb = PIL.Image.fromarray( imgs_comb)
 imgs_comb.save( 'Trifecta.jpg' )    

 # for a vertical stacking it is simple: use vstack
 imgs_comb = np.vstack( (np.asarray( i.resize(min_shape) ) for i in imgs ) )
 imgs_comb = PIL.Image.fromarray( imgs_comb)
 imgs_comb.save( 'Trifecta_vertical.jpg' )

см. Объединить несколько изображений по горизонтали с Python

...