2017-05-26 15 views
1

私はそうのようなDjangoのウェブサイトにアップロードされたPDFファイルのテキストを取得するために杖とpytesseractを使用しています:ワンドのメモリ使用量を減らすには?

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サーバにセロリで実行されています。しかし、image_pdfは13.7 MB pdfファイルでも約4 GBに増加するため、oom killerによって停止されています。より高いラムを支払う代わりに、私はワンドとImageMagickが使用するメモリを減らそうとします。それはすでに非同期なので、計算時間の増加は気にしません。私はこれをスキップしました:http://www.imagemagick.org/Usage/files/#massiveですが、ワンドで実装できるかどうかはわかりません。もう一つの可能​​な修正は、一度に全画像をRAMに入れるのではなく、一度に1ページずつPDFを開く方法です。あるいは、私はこれらのメモリ制限技術を使うことができるように、Pythonを使ってImageMagickと直接インターフェースすることができますか?

答えて

1

ライブラリはMagickWand APIと統合され、PDFエンコーディング/デコードの作業をghostscriptに委譲しています。両方ともMagickWand & ghostscriptには追加のメモリリソースが割り当てられており、各タスクの最後に割り当てを解除することをお勧めします。しかし、ルーチンがPythonで初期化され、変数によって保持されている場合、メモリリークを引き起こす可能性はあります。

メモリを正しく管理するためのヒントをいくつか紹介します。

  1. withすべてのワンド割り当てにコンテキスト管理を使用してください。これにより、すべてのリソースが__enter__ & __exit__管理ハンドラを通過することが保証されます。

  2. データを渡すためにblobの作成を避ける。ファイル形式のブロブを作成するとき、MagickWandは&をコピーするために追加のメモリを割り当て、イメージは元のワンドインスタンスに加えて結果データも保持します。通常、開発環境では問題ありませんが、本番環境ではすぐに手を抜くことができます。

  3. Image.sequenceを避けてください。これはもう一つのコピー重いルーチンであり、結果としてpythonはたくさんのメモリ資源を持っています。 ImageMagickはイメージスタックを非常にうまく管理しているので、個々のフレームを並べ替えたり操作したりしない場合は、MagickWandのメソッド&をpythonに関係なく使用することをお勧めします。

  4. 各タスクは独立したプロセスであり、完了するときれいにシャットダウンできます。これは、キューワーカーとしてceleryと一緒には問題ではありませんが、スレッド/ワーカーの設定+ドキュメントをダブルチェックする価値があります。

  5. 解像度に注意してください。 300 @ 16Qのpdf解像度は、大量のラスターイメージになります。多くのOCR(tesseract/opencv)技術では、最初のステップは、受信データをに事前処理して、 extra/unneeded colors/channels/data/& 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) 

もちろん、あなたの能力は異なる場合があります。で快適であれば、gs & tesseractを直接実行し、すべてのPythonラッパーを削除することができます。

関連する問題