2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NDLOCR-LiteのONNXモデルを使って.NETで画像からテキストの読み取りを行なう

2
Posted at

:star: はじめに

国立国会図書館(NDL)が公開しているNDLOCR-LiteはPythonで実装されていますが、モデルはONNX形式で提供されているため、他の言語からも利用できます。

今回はこのNDLOCR-LiteのONNXモデルを使って.NET/C#で古典籍OCRを行なうサンプルを作成してみたので、その内容について記述します。

:pencil: 概要

ソースコード

今回作成したサンプルの完全なコードは以下のリポジトリにあります。
以降の解説はこのソースコードに沿って説明していきます。

実行環境

項目 概要
OS Windows 11
言語/ランタイム C#/.NET 10
推論エンジン ONNX Runtime
レイアウト検出モデル DEIM-S
文字認識モデル PARSeq

使用ライブラリ

ライブラリ 用途
Microsoft.ML.OnnxRuntime.DirectML ONNX推論エンジン
SkiaSharp 画像の読み込み、リサイズ、回転等の画像処理
YamlDotNet 検出クラス定義、文字セットの読み込み

処理フロー

アプリケーションは以下の2段階のパイプラインで処理を行います。

  1. レイアウト検出: DEIM-Sモデルで画像中のテキスト行領域を検出し、バウンディングボックスを取得
  2. 文字認識: 検出した各テキスト行領域を切り出し、PARSeqモデルで文字を認識

Ocr名前空間のクラス構成

OCR処理の中核となるクラスはNdlOcrExample.Ocr名前空間に配置しています。

クラス 分類
DeimDetector レイアウト検出
ParseqRecognizer 文字認識
PixelNormalizer 画像前処理(共通)
DetectResult 検出結果データ
  • DeimDetector: 入力画像の前処理、DEIM-Sモデルによる推論、信頼度フィルタリング・NMSを含む後処理を実施して、テキスト行のバウンディングボックスを返します
  • ParseqRecognizer: 切り出されたテキスト行画像の前処理、PARSeqモデルによる推論、logitsからのGreedy Decodingを実施してテキストを返します
  • PixelNormalizer: 画像のピクセルデータをONNXモデル入力用のfloatテンソルに変換するクラスです
  • DetectResult: クラス名、信頼度、バウンディングボックスの座標(X, Y, Width, Height)を保持するデータクラスです

:mag: レイアウト検出 (DEIM)

レイアウト検出にはDEIM-SのONNXモデルを使用しています。

項目
モデル deim-s-1024x1024.onnx
クラス定義 ndl.yaml
入力サイズ 1024x1024 RGB
出力 クラスID、バウンディングボックス座標、信頼度スコア
検出クラス数 17種類(うちテキスト行関連6種類を使用)

モデルは17種類のレイアウト要素を認識できますが、本サンプルではテキスト行に関するクラス(line_mainline_captionline_adline_noteline_note_tochuline_title)のみをフィルタリングして使用しています。

モデルの初期化

NDLOCR-LiteのDEIM-Sモデルは2つの入力を持っています。

入力 形状
images float32 [1, 3, 1024, 1024]
orig_target_sizes int64 [1, 2]

imagesは正規化済みのRGB画像テンソル、orig_target_sizesは入力画像のサイズ(高さ, 幅)です。

InputMetadataの1つ目のエントリからは入力名(images)と画像テンソルの形状を取得し、そこからモデルが期待する入力サイズ(1024x1024)を読み取ります。
2つ目のエントリからは画像サイズ入力の名前(orig_target_sizes)を取得します。
これらの入力名はsession.Run()に渡すNamedOnnxValueの名前として使用します。

前処理

入力画像はアスペクト比を維持したまま1024x1024にリサイズし、余白部分は黒で埋めます。
ピクセル値の正規化にはImageNetの統計値を使用し、RGBA8888形式からRGBチャネル毎のplanar形式のfloatテンソルに変換します。
ピクセル正規化処理はPixelNormalizerクラスでSIMDを使った形で実装しています。

前処理の結果、以下の2つのテンソルを作成してONNXランタイムに渡します。

テンソル 形状
画像テンソル DenseTensor<float> [1, 3, 1024, 1024]
サイズテンソル DenseTensor<long> [1, 2]

画像テンソルは正規化済みのRGB画像で、RGBの各チャネルがplanar配置されています。
サイズテンソルにはモデルの入力サイズ[1024, 1024]を格納します。

後処理

推論結果からテキスト行の検出結果を取得する後処理では、以下のフィルタリングを行います。

  1. 信頼度フィルタリング: 閾値(デフォルト0.5)以下の検出を除外
  2. クラスフィルタリング: line_で始まるクラス名のみを対象とする
  3. 座標変換: モデル空間(1024x1024)の座標をパディング前の元画像の座標系に変換し、画像範囲外の座標をクリッピング
  4. NMS (Non-Maximum Suppression): 重複する検出結果を除去

NMS

信頼度の高い順にソートし、IoU(Intersection over Union)が閾値(0.2)以上の検出結果を抑制することで、同一のテキスト行に対する重複検出を除去します。

:abc: 文字認識 (PARSeq)

文字認識にはPARSeqのONNXモデルを使用しています。

項目
モデル parseq-ndl-16x768-100-tiny-165epoch-tegaki2.onnx
文字セット定義 NDLmoji.yaml
入力サイズ 16x768 BGR
最大認識文字数 100文字
文字セット 約27,000文字(ひらがな、カタカナ、漢字、英数字、記号等)

モデルの初期化

PARSeqモデルの入力は1つです。

入力 形状
input float32 [1, 3, 16, 768]

正規化済みのBGR画像テンソルです。

InputMetadataから入力名(input)とテンソルの形状を取得し、モデルが期待する入力サイズ(16x768)を読み取ります。

前処理

レイアウト検出で得られたバウンディングボックスを元画像からテキスト行領域として切り出し、PARSeqモデルの入力用に前処理を行います。

前処理の結果、以下のテンソルを作成してONNXランタイムに渡します。

テンソル 形状
画像テンソル DenseTensor<float> [1, 3, 16, 768]

BGRのチャネル順でplanar配置され[-1, 1]の範囲に正規化された画像テンソルになります。
DEIM-SとはRGB/BGRのチャネル順と正規化方法が異なります。

デコード

推論結果のlogits(各タイムステップ×約27,000クラスのスコア)からGreedy Decodingで文字列を生成します。
各タイムステップでargmax(最大スコアのインデックス)を取得し、文字セットにマッピングします。

:hammer_pick: 実行結果

次のような画像に対して読み取りを実施してみた時の結果を示します。

input.jpg

> NdlOcrExample -f input.jpg
Device: CPU
Loading configuration files...
Configuration files loaded (charset: 7145 chars, 97ms)
Initializing detection model...
Detection model initialized (1436ms)
Initializing recognition model...
Recognition model initialized (100-char model, 2128ms)
Loading image: input.jpg
Image loaded (size: 240 x 350, 30ms)
Running layout detection...
Layout detection complete: 5 text lines detected (486ms)
Running character recognition...
Character recognition complete: 5 lines recognized (264ms)
Total processing time: 4445ms
========== OCR Results ==========
[line_title] score=0.806 pos=(50,208) size=139x31
  WARNING
[line_main] score=0.788 pos=(49,272) size=143x15
  state of emergency
[line_title] score=0.781 pos=(15,293) size=216x52
  TOTI
[line_title] score=0.776 pos=(10,76) size=222x110
  会議
[line_main] score=0.674 pos=(69,250) size=101x16
  緊急事態発生

:rabbit: うさコメ

NDLOCR-LiteのモデルはONNX形式で提供されているので、.NETでも簡単にOCR処理を実現できました( ˙ω˙)

以下の記事でも顔認識に使用していますが、Microsoft.ML.OnnxRuntimeを使えば.NETアプリケーションに推論機能を簡単に導入でき、今回はそれをOCR用途に適用した形になります。

2
4
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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?