10
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

pdfをOCR処理してテキスト付きpdfをつくる(範囲攻撃)

Posted at

全文検索に引っかかるように、pdf文書にOCR処理をしてテキスト付きpdf化します。
複数ファイルをまとめて処理します。

印刷した活字をキーワードで検索する様な使い方であれば、精度も問題無いと感じました。
今回、追加の学習などはしていませんが、素のままでは手書き文字の変換は難しいですね。
手書きの日本語は「がんばりましょう」な感じでしたが、数字は思った以上に読み取ってくれました。

#作業環境
Windows10 Pro 64bit
Python3.7 / Anaconda

#処理の概要
今回のやり方ではpdfファイルから直接OCR処理できる訳ではありません。今回主役となるtesseractでは、png, jpg等の画像ファイルからでないとテキスト付きpdfが得られないので、下の様に迂回します。
  ○変換したいpdf
    →ページごとに分割 & png化
    →OCR処理
    →バラバラのテキスト付きpdf
    →1つのpdfファイルに結合

「変換したいpdf」が複数ある場合は、これを繰り返します。

#作業手順
「最新のポルシェが最良のポルシェである」の言葉に従い、一番下の各記事を参考にして、それぞれ現時点で最新っぽいVer.をインストールしました。ポルシェに乗ったことはありません。

1)poppler-0.68.0、poppler-data-0.4.10言語ファイルの追加、環境変数pathの設定
  ー パスを通すというのが「???」で、理解に時間が掛かりました。
2)tesseract-OCR 5.0.0 alpha/2021-05-06
  ー LSTMとか素敵!
3)pipで以下を導入。
  ー jupyter内でpipが使えるんですね。

pip install pdf2image    # --> 1.15.1
pip install fitz    # --> 0.0.1.dev2
pip install PyMuPDF    # --> 1.18.14

当初、情報が多かったことから、終盤のpdfファイルの結合は PyPDF2 で検証を進めていましたが、最後の最後で「ファイル名に日本語が含まれているとエラーになる」ことがわかり、fitz(PyMuPDF) に変更しました。

#構成とコード
OCR処理したいpdfファイルを "file_in" に配置、pdfOCR.ipynbを実行すると "operate" で作業し "ocr_out" に出力します(出力処理後、"operate" 下のファイルは削除)。
.
┣ pdfOCR.ipynb(プログラム本体)
┣ file_in(対象ファイル投下用)
┣ operate(作業用)
┗ ocr_out(OCR後のpdf出力用)

pdfOCR.ipynb
import os
import glob
import pdf2image
import fitz

input_dir = 'file_in\\'
operate_dir =  'operate\\'
output_dir = 'ocr_out\\'

only_pdf = '*.pdf'    #pdfに限定
only_png = '*.png'
all_f = '*.*'

input_dir_pdf = input_dir + only_pdf
operate_dir_png = operate_dir + only_png
operate_dir_pdf = operate_dir + only_pdf
operate_dir_all = operate_dir + all_f

input_files = glob.glob(input_dir_pdf)    #入力pdfファイルのリスト取得

for ipf in input_files:
    images = pdf2image.convert_from_path(ipf)    #dpi=200
    file_name = os.path.splitext(ipf)[0]
        
    for index, image in enumerate(images):    #ページごとに分割してpng保存 --> operate_dir
        img_fn = file_name + '-' + str('{:0=4}'.format(index+1))    #-0000
        img_fn_op = img_fn.replace(input_dir,operate_dir)
        image.save(img_fn_op + '.png')

png_files = glob.glob(operate_dir_png)    #作業用ディレクトリ内pngのリスト取得

for pnf in png_files:    #OCR処理のメイン:png --> pdf+OCR
    pdf_name = os.path.splitext(pnf)[0]
    !tesseract {pnf} {pdf_name} -l jpn+eng --psm 3 pdf
    
pdf_files = glob.glob(operate_dir_pdf)    #作業用ディレクトリ内pdfのリスト取得

merge_fns=[]    #入出力複数ファイル対応用の箱

for iof in input_files:    #入力ファイル名 --> 出力ファイル名をつくる
    fna = os.path.splitext(iof)[0]
    merge_fn = fna + '_OCR_.pdf'
    merge_fn_out = merge_fn.replace(input_dir, output_dir)
    merge_fns.append(merge_fn_out)

for mfn in merge_fns:    #同じファイル名のpdfを結合
    mf = os.path.splitext(mfn)[0][:-5]
    mfc = mf.replace(output_dir, '')
    
    mg_f = fitz.open()  #結合先

    for pff in pdf_files:
        pf = os.path.splitext(pff)[0][:-5]
        pfc = pf.replace(operate_dir, '')

        if mfc == pfc:
            cmb_f = fitz.open(pff)  #結合するページ
            
            mg_f_lp = len(mg_f)
            cmb_f_lp = len(cmb_f)
            
            mg_f.insertPDF(cmb_f, from_page=0, to_page=cmb_f_lp,  #結合するファイルの最初から最後までを
                          start_at=mg_f_lp)                       #結合先の最後のページに続けて
            
            cmb_f.close()
    mg_f.save(mfn)

for rmvf in glob.glob(operate_dir_all):    #作業用ディレクトリのファイル削除
    if os.path.isfile(rmvf):
        os.remove(rmvf)

tesseractでは、jpn+eng → eng+jpn にすると精度が変わるかもしれません。また文章の抽出ではなく、キーワード検索のレベルであれば、psm6より3の方が良さそうでした。それほど深く追求した訳ではないですけど。
変換したいpdfファイルは、10,000ページ未満/ファイル を想定してます。

#備考
元のファイル名にスペースが含まれているとtesseractのエラーが出ます。事前に処理しておきましょう。

#参考
ありがたや、ありがたや。
  Poppler : PDFのコマンドラインツール
  Windows 10でPath環境変数を設定/編集する
  Tesseract at UB Mannheim
  PythonとTesseract OCRで文字認識
  PythonでPDFを複数まとめて自動結合!日本語ファイルを1つに集約
  スキャンしたpdfファイルにOCR処理を行い,テキスト埋め込みpdfを作成する
  Pythonでファイル・ディレクトリを削除するos.remove, shutil.rmtreeなど
  Qiita Markdown 書き方 まとめ

10
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?