はじめに
こんにちは。Daddy's Officeの市川です。
私が10年以上開発を続けているWindowsPCを監視カメラシステムにする「LiveCapture3」。
先日、このソフトにOCR機能を追加して、カメラ映像内の数値を検出できるようにしました。
(この機能により、サーマルカメラを使用した自動温度計測&通知システムの構築が可能です)
「LiveCapture3」のコア機能はC++で実装しているので、C++でOCR機能を実装する必要がありました。
C++でのOCRといえば、「Tesseract」が有名ですが、今回は画像内の数値のみ検出すればよく、そこまで大掛かりにしたくありませんでした。
そこでWindowsのAPIを調べたところ、ありました!
Windows.Media.Ocr
しかし、よくよく見てみると、これはWinRTっぽい感じ。
つまり、UWPアプリやストアアプリであれば使えるのですが、デスクトップアプリから使うにはちょっと細工が必要そうです。
ということで
- WinRTのWindows.Media.Ocrを.NetFrameworkのC#で使えるようにする
- 上記のC# .NetFrameworkモジュールをC++から使えるようにする
という2段階で実装しました。
WinRTのWindows.Media.Ocrを.NetFrameworkで使う
言語としてはどちらもC#なので、参照を追加できれば基本はOKです。
まず、.NetFrameworkのクラスライブラリとしてプロジェクトを生成します。
OCRを使用する為には、下記のUWPライブラリが必要です。
- Windows.Media.Ocr
- Windows.Storage.Streams
- Windows.Graphics.Imaging
これらを使えるようにするために、プロジェクトの参照で、直接ライブラリを追加します。
追加するのは下記の2つです。
名前 | パス |
---|---|
Windows.Foundation.UniversalApiContract | C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.UniversalApiContract\8.0.0.0\Windows.Foundation.UniversalApiContract.winmd |
Windows.Foundation.FoundationContract | C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd |
これで、準備はできました。
OCRエンジンの使い方は非常に簡単で、画像を渡すと認識結果の文字列が返却されるというものです。
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage.Streams;
async Task<OcrResult> detect(SoftwareBitmap bitmap)
{
var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
var ocrResult = await ocrEngine.RecognizeAsync(bitmap);
return ocrResult;
}
ただ、面倒くさいのが
- 引数の画像はSoftwareBitmap(WinRT)を使う必要がある
- WinRTのAsyncは、デスクトップのasync/awaitとは違う形式になっている
というところを解決しないといけません。
色々調べた結果、以下に素晴らしい説明がありました!
Microsoft OCR をデスクトップのWFPアプリで動かす方法
参照追加の方法がちょっと違いますが、実装コードはこのまま行けました!
.NetFrameworkライブラリをC++からコールする
これは、以前私が投稿した下記のやり方で行います。
既存のC++ネイティブプロジェクトでC#マネージドコードを使う
これで、Native C++からWinRT用のOCR APIをコールしてOCR機能を実現することができました!
ソースコード
ソースコード一式(VisualStudio2019)はこちらに置いておきます。
#参考
Microsoft OCR をデスクトップのWFPアプリで動かす方法
既存のC++ネイティブプロジェクトでC#マネージドコードを使う