41
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Rust/WinRT] 画像文字認識 (OCR)

Posted at

昨日「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-DEja など) は後で使用します.

$ cargo run
de-DE: ドイツ語 (ドイツ)
ja: 日本語

参考文献: OcrEngine.AvailableRecognizerLanguages Property

画像文字認識

コマンドライン引数として画像ファイルのパスを与えると OCR を実行し, その結果を出力するというプログラムを作成してみます. ここでは簡単のため入力は PNG に限ることにします.

先に main 関数を示しておきます. 見ての通り open_imageocr というふたつの関数を定義するのが目標です.

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 ファイルに対してこのプログラムを実行してみます.

Constitution_of_Japan.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

フォントのせいか, それとも題材のせいか, 先ほどよりは成績が悪いです. 「山 料」は惜しい… でもそれなりに読めていますし, とても簡単に利用できることを考えるとこんなものでしょうか.

参考文献

41
44
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
41
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?