環境
- Windows 10
- Python 3.7.1 (Anaconda3-2018.12-Windows-x86_64)
- PyOCR
- Tesseract OCR 4.0.0
画像をOCRするやつの並列化版
前回の画像をOCRして検索用のテキストファイルを作るだとシングルスレッドで処理するので遅かった。
標準ライブラリに入っているPoolというやつを使うとmapするときに並列処理できるらしいので、それに合わせてOCR処理を書き換えた。
pyocrとTesseract OCRが並列で呼び出しても問題ないIFになっているかどうか不安だったが、OCRする度にTesseract OCRを新たに呼び出す設計で問題なかった(少なくとも上記環境では)。
from PIL import Image
import sys
import pyocr
import pyocr.builders
import glob
import os
from multiprocessing import Pool
import multiprocessing as multi
def ocrimage(file):
tools = pyocr.get_available_tools()
if len(tools) == 0:
print("No OCR tool found")
sys.exit(1)
# The tools are returned in the recommended order of usage
tool = tools[0]
print("Will use tool '%s'" % (tool.get_name()))
# Ex: Will use tool 'libtesseract'
langs = tool.get_available_languages()
print("Available languages: %s" % ", ".join(langs))
lang = langs[0]
print("Will use lang '%s'" % (lang))
ocrtext = tool.image_to_string(
Image.open(file),
lang="jpn",
builder=pyocr.builders.TextBuilder(tesseract_layout=6)
)
return ocrtext
if __name__ == '__main__':
njobs = 1
if multi.cpu_count() > 2:
njobs = multi.cpu_count() - 1
ocrtext = ""
filelist = []
for p in glob.glob('./**', recursive=True): # ディレクトリとファイル取得
if os.path.isfile(p):
# ファイルの場合
name,ext = os.path.splitext(p)
if ".jpg" == ext or ".png" == ext or ".gif" == ext:
filelist.append(p)
# 並列処理
process = Pool( njobs )
ocrtexts = process.map(ocrimage, filelist)
process.close()
for index, p in enumerate(filelist):
ocrtext += p + ":\n" + ocrtexts[index] + "\n\n"
f = open('ocrtext.txt', 'w', encoding='utf-8')
f.write(ocrtext)
f.close()
前回はRyzen7 2700X(8コア16スレッド)で1スレッドしか使ってなかったので約2500個の画像に1時間ぐらい掛かっていたが、今回のコードで10分程度に高速化した。
HyperThreadingなどのSMTはCPUの空きパイプラインを活用して5-20%程度性能を改善するらしいのだが、実コア数を超えた時点でPCの動作が重くなる。
multi.cpu_count()が返すのはどうも論理コア数らしいので、実コア数に合わせたい感はある。
論理コア数を全部使い切られるとPCが大変重くなって作業できなくなるので一応-1している。
余談だが、if __name__ == '__main__':
を忘れたせいで1時間半損した。
2/27追記: なんか"UnicodeEncodeError: 'cp932' codec can't encode character ..."とエラーが出た。
書き込み時のエンコーディング指定忘れが原因だった。ちゃんとencoding='utf-8'
をつけましょう…。