OpenVINO™ を使用した手書き中国語と日本語の OCR
この Jupyter ノートブックはオンラインで起動でき、ブラウザーのウィンドウで対話型環境を開きます。ローカルにインストールすることもできます。次のオプションのいずれかを選択します:



このチュートリアルでは、手書きの中国語 (簡体字) と日本語の光学文字認識 (OCR) を実行します。ラテン・アルファベットを使用した OCR チュートリアルは、ノートブック 208 で入手できます。このモデルは、一度に 1 行のシンボルのみを処理できます。
このノートブックで使用されているモデルは、handwritten-japanese-recognition-0001 と handwritten-simplified-chinese-0001 です。モデル出力を読み取り可能なテキストとしてデコードするには、kondate_nakayosi と scut_ept 文字リストが使用されます。どちらのモデルも Open Model Zoo で入手できます。
目次:
import platform
# openvino-dev パッケージをインストール
%pip install -q "openvino>=2023.1.0" opencv-python tqdm
if platform.system() != "Windows":
%pip install -q "matplotlib>=3.4"
else:
%pip install -q "matplotlib>=3.4,<3.7"
Note: you may need to restart the kernel to use updated packages.
Note: you may need to restart the kernel to use updated packages.
インポート
from collections import namedtuple
from itertools import groupby
import cv2
import matplotlib.pyplot as plt
import numpy as np
import openvino as ov
# `notebook_utils` モジュールを取得
import requests
r = requests.get(
url="https://raw.githubusercontent.com/openvinotoolkit/openvino_notebooks/latest/utils/notebook_utils.py",
)
open("notebook_utils.py", "w").write(r.text)
from notebook_utils import download_file
設定
このノートブックで使用されるすべての定数とフォルダを設定します
# データが配置されるディレクトリー
base_models_dir = "models"
data_folder = "data"
charlist_folder = f"{data_folder}/text"
# モデルで使用される精度
precision = "FP16"
ファイルをグループ化するには、コレクションを定義する必要があります。これには namedtuple
を使用します。
Language = namedtuple(typename="Language", field_names=["model_name", "charlist_name", "demo_image_name"])
chinese_files = Language(
model_name="handwritten-simplified-chinese-recognition-0001",
charlist_name="chinese_charlist.txt",
demo_image_name="handwritten_chinese_test.jpg",
)
japanese_files = Language(
model_name="handwritten-japanese-recognition-0001",
charlist_name="japanese_charlist.txt",
demo_image_name="handwritten_japanese_test.png",
)
言語を選択
選択に応じて、下のセルのコード行を変更する必要があります。
日本語のテキストに対して OCR を実行するには、language = "japanese"
を設定します。中国語の場合は、language = "chinese"
を設定します。
# language="chinese" または language="japanese" のいずれかをの言語を選択
language = "chinese"
languages = {"chinese": chinese_files, "japanese": japanese_files}
selected_language = languages.get(language)
モデルのダウンロード
画像と文字リストに加えて、モデルファイルをダウンロードする必要があります。以下のセクションには、中国語または日本語のモデルをダウンロードするセルがあります。
ノートブックを初めて実行すると、モデルがダウンロードされます。これには、数分かかる場合があります。
utils パッケージの download_file
関数を使用すると、ディレクトリー構造が自動的に作成され、選択したモデルファイルをダウンロードできます。
path_to_model = download_file(
url=f"https://storage.openvinotoolkit.org/repositories/open_model_zoo/2023.0/models_bin/1/{selected_language.model_name}/{precision}/{selected_language.model_name}.xml",
directory=base_models_dir,
)
_ = download_file(
url=f"https://storage.openvinotoolkit.org/repositories/open_model_zoo/2023.0/models_bin/1/{selected_language.model_name}/{precision}/{selected_language.model_name}.bin",
directory=base_models_dir,
)
models/handwritten-simplified-chinese-recognition-0001.xml: 0%| | 0.00/108k [00:00<?, ?B/s]
models/handwritten-simplified-chinese-recognition-0001.bin: 0%| | 0.00/32.9M [00:00<?, ?B/s]
モデルをロードして実行
すべてのファイルがダウンロードされ、言語が選択されたら、ネットワークを読み取ってコンパイルし、推論を実行します。モデルへのパスは、選択した言語に基づいて定義されます。
core = ov.Core()
model = core.read_model(model=path_to_model)
推論デバイスの選択
OpenVINO を使用して推論を実行するためにドロップダウン・リストからデバイスを選択します
import ipywidgets as widgets
device = widgets.Dropdown(
options=core.available_devices + ["AUTO"],
value="AUTO",
description="Device:",
disabled=False,
)
device
Dropdown(description='Device:', index=1, options=('CPU', 'AUTO'), value='AUTO')
compiled_model = core.compile_model(model=model, device_name=device.value)
画像のロード
次に、画像を読み込みます。モデルは入力として単一チャネルの画像を想定しているため、画像はグレースケールで読み取られます。
入力画像を読み込んだ後、必要な入力レイヤーの高さと現在の画像の高さのスケール比の計算に必要な情報を取得します。下のセルでは、文字の比率を維持し、入力された形状に合うように、画像のサイズが変更され、パディングされます。
# 選択したモデルに基づいて、openvino_notebooks ストレージからイメージをダウンロード
file_name = download_file(
"https://storage.openvinotoolkit.org/repositories/openvino_notebooks/data/data/image/" + selected_language.demo_image_name,
directory=data_folder,
)
# テキスト検出モデルでは、グレースケール形式の画像が必要
# 重要: このモデルでは、一度に 1 行のみを読み取ることができます
# 画像を読み取り
image = cv2.imread(filename=str(file_name), flags=cv2.IMREAD_GRAYSCALE)
# 形状を取得
image_height, _ = image.shape
# B,C,H,W = バッチサイズ、チャネル数、高さ、幅。_, _, H, W = recognition_input_layer.shape
# 入力された画像の高さと高さの間のスケール比を計算して、画像のサイズを変更
scale_ratio = H / image_height
# 予想される入力サイズに合わせて画像のサイズを変更
resized_image = cv2.resize(image, None, fx=scale_ratio, fy=scale_ratio, interpolation=cv2.INTER_AREA)
# アスペクト比を変更せずに、入力サイズに合わせて画像をパディング
resized_image = np.pad(resized_image, ((0, 0), (0, W - resized_image.shape[1])), mode="edge")
# ネットワーク入力に合わせて形状を変更
input_image = resized_image[None, None, :, :]
data/handwritten_chinese_test.jpg: 0%| | 0.00/42.1k [00:00<?, ?B/s]
文字リストを準備
モデルが読み込まれ、画像が準備できました。残っている要素は、ダウンロードされる文字リストのみです。使用する前に、文字リストの先頭に空白記号を追加する必要があります。これは中国モデルと日本モデルの両方で予想されます。
# 選択したモデルに基づいて、openvino_notebooks ストレージからイメージをダウンロード
used_charlist_file = download_file(
"https://storage.openvinotoolkit.org/repositories/openvino_notebooks/data/data/text/" + selected_language.charlist_name,
directory=charlist_folder,
)
data/text/chinese_charlist.txt: 0%| | 0.00/15.8k [00:00<?, ?B/s]
# モデルのドキュメントに基づいて、出力をエンコードする辞書を取得
used_charlist = selected_language.charlist_name
# どちらのモデルでも、各文字リストのインデックス 0 に空白記号が追加される必要があります
blank_char = "~"
with used_charlist_file.open(mode="r", encoding="utf-8") as charlist:
letters = blank_char + "".join(line.strip() for line in charlist)
推論の実行
推論を実行します。compiled_model()
関数は、モデル入力と同じ順序の入力のリストを受け取ります。次に、出力テンソルから出力を取得します。
# モデルで推論を実行
predictions = compiled_model([input_image])[recognition_output_layer]
出力データを処理
モデルの出力は W x B x L
形式です:
さらに可読性が高い形式にするには、最も確率の高いシンボルを選択します。最も高い確率を持つと予測されるインデックスのリストを保持する場合、CTC デコードの制限により、同時シンボルを削除してから空白を削除します。
最後に、文字リスト内の対応するインデックスからシンボルを取得します。
# 次元を削除
predictions = np.squeeze(predictions)
# `argmax` 関数を実行して、最も確率の高いシンボルを選択
predictions_indexes = np.argmax(predictions, axis=1)
# CTC 貪欲デコードに必要な同時文字を削除するには、`groupby` 関数を使用
output_text_indexes = list(groupby(predictions_indexes))
# グループ化オブジェクトを削除
output_text_indexes, _ = np.transpose(output_text_indexes, (1, 0))
# 空白の記号を削除
output_text_indexes = output_text_indexes[output_text_indexes != 0]
# 出力配列のインデックスに文字を割り当て
output_text = [letters[letter_index] for letter_index in output_text_indexes]
出力をプリント
これで、モデルによって予測された文字のリストができたので、予測されたテキストが下に印刷された画像を表示できます。
plt.figure(figsize=(20, 1))
plt.axis("off")
plt.imshow(resized_image, cmap="gray", vmin=0, vmax=255)
print("".join(output_text))
人有悲欢离合,月有阴睛圆缺,此事古难全。