目的
PDFはテキストの情報が含まれている場合がありますが、場合によっては画像として文字を使用している場合があります。
今回はOCR機能を使用して画像からテキストを抽出してみます。
https://github.com/mima3/pdf_udon
PDFからの画像取得方法
PyMuPDFを使用すればPDFから画像を簡単に抽出できます。
import fitz
fitz.open('data/賛成0123.pdf')
doc = fitz.open('data/賛成0123.pdf')
pix = doc[0].getPixmap()
pix.writePNG('test.png')
Page.getPixmapメソッドを利用することで、Pixmapのオブジェクトを取得します。ピクセルの情報を保持しており、画像ファイルとして出力することも可能です。
これらの機能を使用してPDFからPNGを抽出するスクリプトが以下になります。
https://github.com/mima3/pdf_udon/blob/master/convert_image.py
OCRでテキストを取得する
今回はOCRでテキストを取得する方法で2種類ためしました。
- Tesseract-OCR
- Googleドキュメント
Tesseract-OCR
Tesseract-OCRはOpenSourceのOCRプログラムで、コマンドラインまたは、ダイナミックリンクのライブラリとして使用できます。
また、PyOCRを使用することでPythonから使用可能です。
詳しくは、GAMMASOFTの資料がわかりやすいです。
Tesseract OCR をWindowsにインストールする方法
https://gammasoft.jp/blog/tesseract-ocr-install-on-windows/
PythonでOCRを実行する方法
https://gammasoft.jp/blog/ocr-by-python/
単純なサンプル
以下が単純なサンプルになります。
この例ではPillowを使用してPNGファイルを読み取り、その内容をpyocrに渡しています。
import pyocr
import pyocr.builders
from PIL import Image
# tesseractをインストールしたフォルダにパスが通っていること
tools = pyocr.get_available_tools()
text=tools[0].image_to_string(
Image.open('test.png'),
lang='jpn',
builder=pyocr.builders.TextBuilder()
)
print(text)
OpenCVを使用して画像に加工をする場合
もし、OpenCVで何らかの画像の処理をしてからpyocrに渡す場合は以下のようになります。
import pyocr
import pyocr.builders
import numpy as np
import cv2
from PIL import Image
def imread_jp(image_full_path):
# cv2::imereadは日本語を含むパスを読めない
# https://github.com/opencv/opencv/issues/4292
# https://stackoverflow.com/questions/11552926/how-to-read-raw-png-from-an-array-in-python-opencv
with open(image_full_path, 'rb') as img_stream:
file_bytes = np.asarray(bytearray(img_stream.read()), dtype=np.uint8)
img_data_ndarray = cv2.imdecode(file_bytes, cv2.IMREAD_UNCHANGED)
return img_data_ndarray
# OpenCVを使用した何らかの処理
img = imread_jp('test.png')
img = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
# tesseractをインストールしたフォルダにパスが通っていること
tools = pyocr.get_available_tools()
text=tools[0].image_to_string(
Image.fromarray(img),
lang='jpn',
builder=pyocr.builders.TextBuilder()
)
print(text)
下記の実装ではノイズの除去だけでなく角度の調整も行っています。
https://github.com/mima3/pdf_udon/blob/master/convert_text.py
テキスト座標の取得
TextBuilder()の代わりに、LineBoxBuilder(),WordBoxBuilder()を使用することで、行の位置や単語の位置も取得できます。
import pyocr
import pyocr.builders
from PIL import Image
# tesseractをインストールしたフォルダにパスが通っていること
tools = pyocr.get_available_tools()
line_boxs=tools[0].image_to_string(
Image.open('test.png'),
lang='jpn',
builder=pyocr.builders.LineBoxBuilder()
)
for line_box in line_boxs:
# 件 名 : バブ リッ クコ メン ト へ の 意見 ((68, 182), (235, 191))
print(line_box.content, line_box.position)
for word_box in line_box.word_boxes:
print(' ', word_box.content, word_box.position)
出力例
件 名 : バブ リッ クコ メン ト へ の 意見 ((68, 182), (235, 191))
件 ((68, 182), (87, 190))
名 ((80, 172), (92, 200))
: ((99, 172), (106, 200))
バブ ((113, 182), (128, 191))
リッ ((131, 182), (144, 190))
クコ ((148, 183), (165, 191))
メン ((168, 183), (186, 190))
ト ((190, 182), (195, 190))
へ ((197, 184), (204, 190))
の ((207, 183), (215, 190))
意見 ((217, 182), (235, 191))
GoogleドキュメントをOCRとして使う
Googleドライブにアップロードした画像をGoogleドキュメントとして開くことにより、画像に含まれている文字を認識してテキストに変換してくれます。
以下の実装はGoogleDriveのAPIを使用して画像をアップロードして、Googleドキュメントとして開いた内容のテキストを取得するサンプルになります。
https://github.com/mima3/pdf_udon/blob/master/convert_text_googledoc.py
このサンプルを実行するにはGoogle DriveにCSVをアップロードしてGoogleスプレッドシートとして編集後、ダウンロードするで紹介した前提条件を満す必要があります。
なお、Googleドキュメントに変換する場合、どうしてもローカルでtesseractを使用する場合より、速度的に劣ります。
OCR実行結果
今回紹介した方法で香川県のゲーム依存症対策パブリックコメントの画像からテキストを抽出した結果は以下の通りです。
https://github.com/mima3/pdf_udon/releases
ダウンロードすると各方式で取得したテキストを格納したSQLiteが取得できます。