2017-05-26 38 views
1

我使用魔杖,pytesseract獲得上傳到一個Django的網站,像這樣的PDF文本:如何減少魔杖內存使用量?

image_pdf = Image(blob=read_pdf_file, resolution=300) 
image_png = image_pdf.convert('png') 

req_image = [] 
final_text = [] 

for img in image_png.sequence: 
    img_page = Image(image=img) 
    req_image.append(img_page.make_blob('png')) 

for img in req_image: 
    txt = pytesseract.image_to_string(PI.open(io.BytesIO(img)).convert('RGB')) 
    final_text.append(txt) 

return " ".join(final_text) 

我有它在芹菜運行在一個單獨的EC2服務器。但是,由於即使是一個13.7 MB的pdf文件,image_pdf也會增長到大約4 GB,因此它被OOM殺手所阻止。我不想支付更高的內存,我想盡量減少魔杖和ImageMagick使用的內存。由於它已經是異步的,我不介意增加計算時間。我已經剔除了這個:http://www.imagemagick.org/Usage/files/#massive,但我不確定它是否可以用魔杖執行。另一種可能的解決方法是一次一頁地打開一頁pdf,而不是一次將完整的圖像放入RAM中。另外,我怎麼能直接使用Python的ImageMagick接口,以便我可以使用這些內存限制技術?

回答

1

請記住,庫與MagickWand API集成,並將PDF編碼/解碼工作委託給ghostscriptMagickWand & ghostscript都分配了額外的內存資源,並且在每個任務結束時盡最大努力解除分配。但是,如果例程由python初始化,並由變量保存,則引入內存泄漏的可能性更大。

這裏有一些提示,以確保內存管理正確。

  1. 使用with上下文管理爲所有魔杖分配。這將確保所有資源通過__enter__ & __exit__管理處理程序。

  2. 避免blob創建傳遞數據。當創建文件格式blob時,MagickWand將分配額外的內存來複制&對圖像進行編碼,除了原始的魔杖實例之外,python將保存結果數據。在開發環境中通常很好,但可以在生產環境中快速生長。

  3. 避免Image.sequence。這是另一個複製繁瑣的例程,導致python持有一堆內存資源。請記住,ImageMagick管理圖像堆棧的效果非常好,所以如果您不重新排序/操作單個幀,最好使用不涉及python的MagickWand方法。

  4. 每個任務應該是一個孤立的過程,並且可以在完成時乾淨地關閉。對於你來說,這不應該是一個問題,因爲它是隊列工作者,但值得雙重檢查線程/工作者配置+文檔。

  5. 小心分辨率。 300 @ 16Q的pdf分辨率會導致大量的光柵圖像。使用許多OCR(tesseract/opencv)技術,第一步是預處理入站數據到刪除額外/不需要的顏色/通道/數據/ & tc。

下面是我將如何處理這個問題的一個例子。請注意,我將利用直接管理沒有附加python資源的圖像堆棧。

import ctyles 
from wand.image import Image 
from wand.api import library 

# Tell wand about C-API method 
library.MagickNextImage.argtypes = [ctypes.c_void_p] 
library.MagickNextImage.restype = ctypes.c_int 

# ... Skip to calling method ... 

final_text = [] 
with Image(blob=read_pdf_file, resolution=100) as image_pdf: 
    context.depth = 8 
    library.MagickResetIterator(context.wand) 
    while(library.MagickNextImage(context.wand) != 0): 
     data = context.make_blob("RGB") 
     text = pytesseract.image_to_string(data) 
     final_text.append(text) 
return " ".join(final_text) 

當然你的milage可能會有所不同。如果您對感到滿意,則可以直接執行gs & tesseract,並消除所有python包裝。