限りなき知の探訪

45年間、『知の探訪』を続けてきた。いま座っている『人類四千年の特等席』からの見晴らしをつづる。

百論簇出:(第280回目)『シニア・エンジニアのPython事始(その7)』

2024-07-07 10:03:10 | 日記
前回
さて、前回紹介したフランスの百科事典"Grand Dictionnaire Encyclopedique" をダウンロードして、見ようとすると、該当ページを探すのには、幾つもの難関をクリアしなければならない。まず、探し出す項目が何巻の何ページにあるかを突き止めないといけない。索引がないので、各巻に含まれる最初の項目目と最後の項目名から大体どこらあたりにあるかを推測する必要がある。このためにPDFファイルを調べていくとすると、僅か一つの項目を探すのに多大な時間を要する。

問題はそれだけに止まらず、元の紙ベースのページ番号は、テキストページだけに振られていて、図や白紙のページは番号が振られていないことだ。それで、図版などが入っていると、PDFのページと紙ベースのページ数がずれて生じてしまう。これらのことから、紙のページ数とPDFページとの対応表をつくる必要があり、ようやくここでPythonの出番となる。

この作業の概略の手順は以下の通りだ。
1.PDFファイルを各ページ毎に個別のファイルに展開する。 (pdftk の burst 機能を使用)
2. 各ページのPDFファイルを画像(jpg)ファイルに変換する。 (pdfimages で変換)
3.各ページの画像ファイルの上部、つまり、エントリー項目名とページ数が印刷されている部分の画像を切り出す。 (Imagemagick の "convert 機能を使用) (あるいは、pdftoppm を使用しても同等の結果が得られる。)
4.3.で切り出された部分画像をOCR(文字認識)解析して、各PDFページ毎に(ページ数+エントリー項目)の対応リストを作る。 (python の OCR 機能を使用 -- 詳細説明は下記)


これら一連の作業で、1.から3.までは、Web上に存在する既存のソフトをダウンロードして簡単に対応できる。難関は4.のOCRだ。



以前から欧文のOCRには、FreeOCRというソフトを使っていたが、速度の点はともかくも、文字判定精度がかなり低いのには困っていた。とりわけ、今回のような古い時代の印刷物で、PDF用紙に多少歪みがあったり、文字が不鮮明な場合、判定精度はかなり落ちる。しかたないので、以前はオンラインのOCR(https://www.onlineocr.net/ja/、https://ezocr.net/OCR)などを使っていたが、いずれも枚数制限がある上に、判定精度もそれほど高くなかった。

しかし、Pythonでプログラミングが出来るようになって、OCR関連のWeb情報を調べると、Pythonのモジュールにはかなりの精度のものもあることがわかった。とりわけ、Google のVision AI がベストだとの情報があったので、早速試してみると、確かに格段の判定精度で、人間と遜色のないレベルで、逆に非常におどろいてしまった。しかし残念ながら、枚数に制限があるのがネックだ(月間、1000回までは無料)。

以下のコードは、下記サイトを参考にして作成した。
https://qiita.com/ku_a_i/items/93fdbd75edacb34ec610

====================

# -*- coding: Shift-JIS -*-

import pyocr, sys
from PIL import Image, ImageEnhance
import os, re
import glob

global tool;
global builder;
global counter;

def init():
global tool, builder;

#Path
TESSERACT_PATH = 'C:\\Program Files\\Tesseract-OCR' #
TESSDATA_PATH = 'C:\\Program Files\\Tesseract-OCR\\tessdata' #tessdataのpath

os.environ["PATH"] += os.pathsep + TESSERACT_PATH
os.environ["TESSDATA_PREFIX"] = TESSDATA_PATH

#OCR
tools = pyocr.get_available_tools()
tool = tools[0]

#OCR
builder = pyocr.builders.TextBuilder(tesseract_layout=6)

def ocr_image(ff_image, ff_txt):
global tool, builder;

img = Image.open(ff_image);
img_g = img.convert('L') #Gray
enhancer= ImageEnhance.Contrast(img_g) #
img_con = enhancer.enhance(2.0) #

txt_pyocr = tool.image_to_string(img, lang='eng', builder=builder)
ff_out = open(ff_txt, 'w', encoding='utf-8')
ff_out.write(txt_pyocr)
ff_out.close()

def usage():
print("Usage: py -B ocr_mult.py [image*.jpg] [txt prefix]");

def exe_ocr_mult(fname_image, out_prefix):
global counter

img_files = glob.glob(fname_image);
for ffile in img_files:
counter += 1;
tmp = ffile.split(".");
fbase = tmp[0];
outf = str("%s_%s.txt" %(out_prefix, fbase));
print("[%d] [%s] outf[%s]: " %(counter, ffile, outf));
ocr_image(ffile, outf);

#################################
def main():
global counter

counter = 0;
args = sys.argv
len_args = len(args);
fname_image = args[1];

out_prefix = "jj";
if len_args < 2:
usage();
return();

if len_args >= 2:
fname_img = args[1];
if len_args == 3:
out_prefix = args[2];

init();
exe_ocr_mult(fname_image, out_prefix);

if __name__== "__main__":
main();
====================


当然これだけでは、できなくて、見出し文字のインデックスを正しく作るにはまだまだ越えなければいけない山がある。

続く。。。
コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 智嚢聚銘:(第59回目)『中... | トップ | 智嚢聚銘:(第60回目)『中... »
最新の画像もっと見る

コメントを投稿

日記」カテゴリの最新記事