PythonでOCR(その3)

PythonでOCR(その2)では、tiff化したデータからPDFを生成する過程で、実用的では無いほどの大容量PDFになってしまうのが課題でした。その後、テキスト情報を埋め込んだPDFとして最小限の容量増加でPDFを作ることができたので投稿してみます。

開発環境としては、前回の環境に加えて、Windows版のコマンドラインソフトの、「Qpdf」を追加でインストールする必要があります。

処理の流れは以下で検討してみました。

  • 対象のPDFファイルをマルチページtiff形式に変換してみる
  • 変換後のマルチページtiffファイルをtesseractでOCRしてテキスト情報のみのpdfを作成する
  • Qpdfを利用して、オリジナルのPDFとテキスト情報のみのpdfを合体して新たなPDFとして保存する

では、作業記録です。

まずは、Windowsで実行するPDF加工の必須環境としてので、Windows版のQpdfをダウンロードしてインストールします。

https://sourceforge.net/projects/qpdf/files/qpdf/

私は https://sourceforge.net/projects/qpdf/files/qpdf/9.1.1/ から入手しました。

QpdfはWindowsのコマンドプロンプトで実行するタイプのフリーソフトです。Pythonからはsubprocessによりコマンドを呼出して同期処理させること実現しました。

Qpdfインストール後に、環境変数のPathにQpdfの導入先ディレクトリを追加しておかないと、PythonプログラムからQpdfを起動できずにエラーが発生しますので忘れずに。

環境は整ったハズなのでサンプルプログラムと結果サンプルです。

from PIL import Image
import sys
import pyocr
import pyocr.builders
from pdf2image import convert_from_path
import re
import subprocess
import os
from pathlib import Path

tools = pyocr.get_available_tools()
tool = tools[0]
langs = tool.get_available_languages()
print("Available languages: %s" % ", ".join(langs))
lang = langs[1]
print("Will use lang '%s'" % (lang))

# 対象PDFファイル名
Nm='vyvo(raw)'

#配置先ディレクトリ
pdf_path = Path("./pdf_file/"+Nm+".pdf")
txt_path = Path("./txt_file/"+Nm + ".txt")
out_path = Path("./pdf_file/output/"+Nm+".pdf") 


# PDF -> pagesにImageとして変換する(300dpi指定)
# dpiは無意味かも
pages = convert_from_path(str(pdf_path),300)

txt=''
for i, page in enumerate(pages):
    txt = txt + tool.image_to_string(page,lang='jpn',builder=pyocr.builders.TextBuilder(tesseract_layout=6))
    txt = re.sub('([あ-んア-ン一-龥ー])\s+((?=[あ-んア-ン一-龥ー]))',r'\1\2', txt)    
    
#テキストファイル出力
s = txt
with open(txt_path, mode='w') as f:
    f.write(s)

#マルチページのTIFFとして保存する
image_dir = Path("./image_file")
tiff_name = pdf_path.stem + ".tif"
image_path = image_dir / tiff_name
to_pdf = pdf_path.stem + "_TO"
topdf_path = image_dir / to_pdf

#既存ファイル削除
if os.path.exists(image_path):
    os.remove(image_path)
if os.path.exists(str(topdf_path)+'.pdf'):
    os.remove(str(topdf_path)+'.pdf')
    
pages[0].save(str(image_path), "TIFF", compression="tiff_deflate", save_all=True, append_images=pages[1:])

#テキストオンリーpdfの生成
cmd = 'tesseract -c page_separator="[PAGE SEPRATOR]" -c textonly_pdf=1 "' + str(image_path) + '" "' +  str(topdf_path) +'" -l jpn pdf'
print(cmd)
returncode = subprocess.Popen(cmd,shell=True )
returncode.wait()

#オリジナルのpdfにtextonlyのpdfをオーバーレイして最小サイズのpdfを生成してみる。qpdfの基本コマンドは以下
#to.pdf=テキストオンリーpdf org.pdf=オリジナルpdf out.pdf=オーバレイ済pdf
#qpdf --overlay to.pdf -- org.pdf out.pdf
if os.path.exists(out_path):
    print('remove ' + out_path)
    os.remove(out_path)
cmd = 'qpdf --overlay "' + str(topdf_path) + '.pdf" -- "' + str(pdf_path) +'" "' + str(out_path) + '" '
print(cmd)
returncode = subprocess.Popen(cmd,shell=True )
returncode.wait()

感想

前回の結果では実用的ではありませんでしたが、Qpdfを利用してオリジナルのPDFにtesseractでocrしたテキスト情報のみのPDFをオーバーレイする事で、実用的な最小限の増量?に抑えたPDFを作成する事に成功しました。

この処理により、スキャンにより生成したOCR情報を内包しないPDF名を指定して、tesseractでocrして、OCR情報を含んだPDFを作成する処理のアイデアの一つが形になりました。

それなりにCPUPowerを使いますが、Googleドライブを使った処理よりは自由度が高く、用途に合わせて改良できるのではないかと思いますので、参考としてください。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする