Electron製の社内ツールにWindows AI OCRを載せる方法


社内で使っているElectronアプリに「画像から文字を読み取る機能」を追加したい——そんな要望、意外と多いのではないだろうか。領収書の読み取り、手書きメモのテキスト化、スクリーンショットからの情報抽出など、OCRが活躍する場面は幅広い。

Windows App SDKが提供する「Windows AI Text Recognition」を使えば、外部APIに頼らずローカルでOCR処理が完結する。クラウドに画像を送らないので、機密性の高い社内文書を扱う場面でも導入しやすい。この記事では、ElectronアプリにこのWindows AI OCRを組み込む流れを整理していく。

どんな情報が取れるのか

Windows AI Text Recognitionは、単に「画像内の文字列」を返すだけではない。以下の情報がセットで取得できる。

  • 行単位・単語単位のテキスト
  • 各単語の境界ボックス(BoundingBox)
  • 認識の信頼度(Confidence)

信頼度が取れるのは地味にありがたい。Microsoft公式のサンプルでは、信頼度0.33未満を「低信頼」、0.67以上を「高信頼」として色分け表示している。社内ツールなら「信頼度が低い箇所は赤くハイライトして、人間に確認を促す」といったUI設計が可能だ。

従来のWindows.Media.Ocr.OcrEngineと比べると、新しいWindows AI OCRはNPU(Neural Processing Unit)を活用したハードウェアアクセラレーションに対応している。対応デバイスなら処理速度と精度の両方で恩恵を受けられる。ただし、これは裏を返せば「動作環境によって差が出る」ということでもある。全社員のPCにNPUが載っているわけではない場合、パフォーマンスにばらつきが出る点は認識しておきたい。

実装の全体像

ElectronアプリからWindows AI OCRを呼び出すには、いくつかのアプローチがある。WinRT APIをNode.jsから直接叩く方法も理論上は可能だが、現実的には別プロセスでOCR処理を行い、結果をElectronに返す構成がおすすめだ。

具体的には以下のパターンが考えられる。

  • .NET製のコンソールアプリ(CLI)を用意し、Electronから呼び出す
  • ローカルでHTTPサーバーを立て、REST API経由でOCR結果を受け取る

この分離構成にするメリットは大きい。Windows App SDKの依存関係をElectron側に持ち込まずに済むし、OCR処理部分だけを独立してテスト・更新できる。配布時のパッケージングも楽になる。

OCR処理側の実装フロー

Windows AI OCRを使うコード(.NET側)の流れは、ざっくりこうなる。

1. モデルの準備状態を確認する

var readyState = TextRecognizer.GetReadyState();
if (readyState != AIModelReadyState.Ready)
{
    var result = await TextRecognizer.EnsureReadyAsync();
    if (result.Status != AIReadyResultStatus.Success)
    {
        // エラー処理(result.ExtendedErrorで詳細確認)
    }
}

GetReadyState()で「OCRモデルが使える状態か」をまず確認する。未準備ならEnsureReadyAsync()を呼んでモデルを導入する。このとき失敗する可能性があるので、StatusExtendedErrorを見て適切にハンドリングする必要がある。

2. 画像をImageBufferに変換する

// SoftwareBitmapを作成(画像読み込み処理は割愛)
SoftwareBitmap softwareBitmap = /* 画像から取得 */;

// ImageBufferに変換
ImageBuffer imageBuffer = ImageBuffer.CreateCopyFromBitmap(softwareBitmap);

入力画像はSoftwareBitmapを経由してImageBufferに変換する。画像の読み込み方法はいくつかあるが、ファイルパスから読む場合はBitmapDecoderを使うのが一般的だ。

3. OCR実行

var recognizer = await TextRecognizer.CreateAsync();
var result = recognizer.RecognizeTextFromImage(imageBuffer);

foreach (var line in result.Lines)
{
    Console.WriteLine(line.Text);
    foreach (var word in line.Words)
    {
        Console.WriteLine($"  {word.Text} (信頼度: {word.Confidence})");
    }
}

RecognizeTextFromImage()を呼べば、行・単語・信頼度・境界情報がまとめて返ってくる。あとは必要な形式(JSON等)に整形してElectron側に渡せばいい。

Electron側の呼び出し

Electronのメインプロセスから、上で作った.NETのCLIを呼び出す。Node.jsのchild_processを使う形だ。

const { execFile } = require('child_process');

function runOcr(imagePath) {
  return new Promise((resolve, reject) => {
    execFile('./OcrTool.exe', [imagePath], (error, stdout) => {
      if (error) {
        reject(error);
        return;
      }
      resolve(JSON.parse(stdout));
    });
  });
}

CLIがJSON形式で結果を標準出力に吐くようにしておけば、Electron側でパースして表示に使える。境界ボックスの座標も返してもらえば、画像上に矩形をオーバーレイ表示することも可能だ。

精度を上げるための前処理

OCRの精度は入力画像の品質に大きく左右される。Microsoftのドキュメントでも「小さい文字や判読しづらい文字は誤認識しやすい」と明記されている。

実運用で効果があるのは以下のような前処理だ。

  • 解像度の確保:低解像度の画像は拡大してから渡す
  • コントラスト調整:背景と文字のコントラストを強調
  • ノイズ除去:スキャン画像のゴミを取り除く
  • 傾き補正:斜めになっている画像は回転させる

こうした前処理はElectron側(JavaScript/Node.js)で行っても良いし、.NET側で行っても良い。チームのスキルセットに応じて決めればいい。

向いているケース・向いていないケース

この構成が特に活きるのは、以下のような状況だ。

  • 社内の機密文書を扱う(クラウドに送りたくない)
  • オフライン環境でも動かしたい
  • Windows環境に統一されている
  • すでにElectronで社内ツールを作っている

逆に向いていないのは、macOSやLinuxでも動かしたい場合。Windows AI APIはWindows専用なので、クロスプラットフォーム対応が必須ならTesseract.jsなど別の選択肢を検討した方がいい。また、NPU非搭載の古いPCが多い環境では、期待したほどの速度が出ない可能性もある。

始めるならサンプルから

ゼロから書き始めるより、Microsoftが公開しているサンプルコードを起点にするのが効率的だ。GitHubのWindowsAppSDK-SamplesリポジトリにはText Extraction(OCR)のサンプルが含まれていて、モデル準備・画像読み込み・結果表示の一連の流れを追える。

PoCを作るなら、まずこのサンプルを動かして挙動を確認し、そこから自社の要件に合わせてカスタマイズしていくのがスムーズだ。


ローカルで完結するOCRは、クラウドAPIと違って従量課金の心配がない。社内ツールで「ちょっとOCR機能を試したい」というときのハードルがぐっと下がる。Electronアプリを作っているなら、別プロセス構成で組み込むのはそこまで大変ではないので、一度試してみる価値はあると思う。

参考リンク