昨日「Windows Native C++でWinRTのOCR APIを使う方法」という記事を拝見して Win10 が画像文字認識 (OCR) を提供していることを知ったので, Rust/WinRT で試してみました. 驚くほど簡単に PNG 画像を OCR するコンソールアプリが作成できて感動的です.
コード全体はこちら: https://github.com/osanshouo/ocr-by-rust-winrt
準備
環境
本記事のコードは以下の環境で検証しました.
- Windows 10 v1909 build 18363.900
- Rust 1.44.0 stable-x86_64-pc-windows-msvc
- winrt 0.7.0
WinRT のインポート
例によって Rust/WinRT では次の読み込みマクロがコード冒頭に必要です.
winrt::import!(
dependencies
os
types
windows::storage::*
windows::graphics::imaging::*
windows::media::ocr::*
);
使用可能な言語の確認
「設定」→「時刻と言語」→「言語」から確認できるインストール済みの言語による OCR が利用可能です.
use windows::media::ocr::OcrEngine;
fn main() -> winrt::Result<()> {
for lang in OcrEngine::available_recognizer_languages()? {
println!("{}: {}", lang.language_tag()?, lang.display_name()?);
}
Ok(())
}
実行結果の例です. ここで表示される BCP47 言語タグ (de-DE
や ja
など) は後で使用します.
$ cargo run
de-DE: ドイツ語 (ドイツ)
ja: 日本語
参考文献: OcrEngine.AvailableRecognizerLanguages Property
画像文字認識
コマンドライン引数として画像ファイルのパスを与えると OCR を実行し, その結果を出力するというプログラムを作成してみます. ここでは簡単のため入力は PNG に限ることにします.
先に main
関数を示しておきます. 見ての通り open_image
と ocr
というふたつの関数を定義するのが目標です.
fn main() -> winrt::Result<()> {
// 画像ファイルを開きビットマップに変換
let bitmap = open_image()?;
// OCR を実行
ocr(bitmap)
}
画像の読み込み
Win10 の OCR エンジンはビットマップ画像しか認識できないため, まず PNG ファイルをビットマップに変換する必要があります. そこでコマンドライン引数としてファイルパスを取得し, そのパスのファイルを開いて BitmapDecoder
に渡します.
use std::env;
use windows::storage::{StorageFile, FileAccessMode};
use windows::graphics::imaging::{BitmapDecoder, SoftwareBitmap};
fn open_image() -> winrt::Result<SoftwareBitmap> {
// コマンドライン引数の取得
let path = env::args().nth(1).expect("ファイルパスを引数に指定してください.");
// ファイルパスから `StorageFile` オブジェクトを取得
let file = StorageFile::get_file_from_path_async(path)?.get()?;
// ファイルを読み込みビットマップに変換
let bitmap = BitmapDecoder::create_with_id_async(
BitmapDecoder::png_decoder_id()?, // ファイル形式は PNG とする
file.open_async(FileAccessMode::Read)?.get()?
)?.get()?;
// `SoftwareBitmap` 型へ変換
bitmap.get_software_bitmap_async()?.get()
}
参考文献: SoftwareBitmap Class, BitmapDecoder Class, StorageFile Class, ファイルの作成、書き込み、および読み取り
OCR の実行
得られたビットマップ画像に対して OCR を実行します. なお OCR 言語はユーザープロファイルから設定することもできますが, ここでは言語タグを用いて手動設定するようにしました.
use windows::globalization::Language;
use windows::media::ocr::OcrEngine;
// OCR で使用する言語の指定
const LANG: &'static str = "ja";
fn ocr(bitmap: SoftwareBitmap) -> winrt::Result<()> {
// 言語タグをもとに OCR エンジンを生成
let lang = Language::create_language(LANG)?;
let engine = OcrEngine::try_create_from_language(lang)?;
// OCR の実行
let result = engine.recognize_async(bitmap)?.get()?;
// 結果を表示
println!("{}", result.text()?);
Ok(())
}
参考文献: OcrEngine Class, OcrResult Class
実行結果
日本国憲法前文
次の PNG ファイルに対してこのプログラムを実行してみます.
結果はこちら. (見にくいので引用形式にしました)
日 本 国 憲 法 日 本 国 民 は 、 正 当 に 選 挙 さ れ た 国 会 に お け る 代 表 者 を 通 じ て 行 動 し 、 わ れ ら と わ れ ら の 子 孫 の た め に 、 諸 国 民 と の 協 和 に よ る 成 果 と 、 わ が 国 全 土 に わ た っ て 自 由 の も
た ら す 恵 沢 を 確 保 し 、 政 府 の 行 為 に よ っ て 再 び 戦 争 の 参 禍 が 起 る こ と の な い や う に す る こ と を 決 意 し 、 こ こ に 主 権 が 国 民 に 存 す る こ と を 宣 言 し 、 こ の 法 を 確 定 す る 。 そ も そ も 国
政 は 、 国 民 の 厳 粛 な 信 託 に よ る も の て あ っ て 、 そ の 権 威 は 国 民 に 由 来 し 、 そ の 権 力 は 国 民 の 代 表 者 が こ れ を 行 使 し 、 そ の 福 利 は 国 民 が こ れ を 享 受 す る 。 こ れ は 人 類 普 遍 の 原 理 て
あ り 、 こ の 法 は 、 か か る 原 理 に 基 く も の で あ る 。 わ れ ら は 、 こ れ に 反 す る - 切 の 法 、 法 令 及 び 詔 勅 を 排 除 す る 。 日 本 国 民 は 、 恒 久 の 平 和 を 念 願 し 、 人 間 相 互 の 関 係 を 支 配 す る 崇 高 な 理 想 を 深 く 自 覚 す る の で あ っ て 、 平 和 を 愛 す る 諸 国 民 の 公 正 と 信 義 に 信 頼 し て 、 わ れ ら の 安 全 と 生 存 を 保 持 し よ う と 決 意 し た 。 わ れ ら は 、 平 和 を 維 持 し 、 専 制 と 隷 従 、 圧 迫 と 偏 狭 を 地 上 か ら 永 遠 に 除 去 し よ う と 努 め て ゐ る 国 際 社 会 に お い て 、 名 誉 あ る 地 位 を 占 め た い と 思 ふ 。 わ れ ら は 、 全 世 界 の 国 民 が 、 ひ と し く 恐 怖 と 欠 乏 か ら 免 か れ 、 平 和 の う ち に
生 存 す る 権 利 を 有 す る こ と を 確 認 す る 。 わ れ ら は 、 い づ れ の 国 家 も 、 自 国 の こ と の み に 専 念 し て 他 国 を 無 視 し て は な ら な い の で あ っ て 、 政 治 道 徳 の 法 則 は 、 普 遍 的 な も の で あ り
、 こ の 法 則 に 従 ふ こ と は 、 自 国 の 主 権 を 維 持 し 、 他 国 と 対 等 関 係 に 立 た う と す る 各 国 の 責 務 て あ る と 信 す る 。 日 本 国 民 は 、 国 家 の 名 誉 に か け 、 全 力 を あ げ て こ の 崇 高 な 理 想 と 目
的 を 達 成 す る こ と を 誓 ふ 。
なんだか半角スペースが邪魔ですが, それを除けばかなり良いです. 間違いは「参 禍」, 「- 切 の」の二か所でしょうか.
地下鉄路線図
より OCR が難しそうな地下鉄路線図も試してみます. 題材はこちらの京都市営地下鉄です.
結果はこちら.
KO 1 ■ 第 会 館 T15 T14 K02 〇 鳩 1 1 東 都 〇 “ K08 / T13 烏 丸 御 池 T12 〇 町 〇 今 出 掛 〇 第 ロ K04 北 大 第 K03 T11 T10 山 T09 上 ・ 東 西 線 T08 To Line T07 山 料 T03 ■ ・ 〇 ・ 鳩 T06 東 野 烏 丸 線 Karasuma. L1neo 十 条 〇 く い な 橋 〇 竹 出 T02 石 田 T01 六 第 を 京 都 市 営 地 下 鉄 路 線 ■ KYOtO Subway MaD
フォントのせいか, それとも題材のせいか, 先ほどよりは成績が悪いです. 「山 料」は惜しい… でもそれなりに読めていますし, とても簡単に利用できることを考えるとこんなものでしょうか.