UWP の Windows.Media.Ocr.OcrEngine を使って文字認識を実装したのに、言語選択ではウクライナ語が見えるのに結果は空、あるいは文字化け──そんな現場の困りごとに、原因と回避策、そして代替アーキテクチャを実装レベルで整理しました。検証ポイント、落とし穴、コード例、構成サンプルまで網羅します。
UWP の OcrEngine でウクライナ語が認識できない問題
質問概要
- UWP アプリで
Windows.Media.Ocr.OcrEngineを使用しているが、ウクライナ語が候補に見えるものの認識されない。 - OcrEngine でウクライナ語を有効化する方法はあるか?
- 使える代替手段を知りたい。
結論(要点)
- OcrEngine はウクライナ語をサポートしていません。 Windows 標準 OCR が認識できる言語は限定的で、ウクライナ語はカバレッジ外です。
- UWP 側で表示言語・入力言語のパックを追加しても OCR には反映されません。 OCR は OS の別コンポーネント(Windows Capability)で管理されます。
- 実用的な代替は Azure AI Vision(クラウド) または Tesseract(オフライン)、もしくは サードパーティ OCR SDK です。
なぜ「候補に見える」のに認識できないのか
よくある誤解は、「言語の候補に表示される = OCR で認識できる」という思い込みです。UWP/Windows には複数の「言語の概念」があり、それぞれの適用範囲が異なります。
| 分類 | 代表 API / 設定 | 用途 | ウクライナ語が見える可能性 |
|---|---|---|---|
| UI 表示/地域 | Windows.Globalization.ApplicationLanguages、設定 > 時刻と言語 | UI 文言、桁区切り、日付など | あり(言語パックを追加すれば列挙される) |
| キーボード/IME | 言語 > キーボード | 入力方式 | あり |
| OCR 言語 | OcrEngine.AvailableRecognizerLanguages | 文字認識(印刷/手書き) | なし(非サポート) |
つまり、UI 言語や入力言語にウクライナ語が現れても、それは OCR の対応可否とは無関係です。OCR は「Windows の機能(Windows Capability)」として別枠で配布・管理されています。
対応言語の確認方法(管理者の検証手順)
管理者権限の PowerShell で、OS にインストール可能/インストール済みの OCR 言語を一覧できます。
# 管理者 PowerShell
Get-WindowsCapability -Online | Where-Object { $_.Name -Like 'Language.OCR*' } |
Select-Object Name, State
出力は次のようになります(例)。
Name State
---- -----
Language.OCR~~~en-US~0.0.1.0 Installed
Language.OCR~~~ja-JP~0.0.1.0 Installed
Language.OCR~~~de-DE~0.0.1.0 NotPresent
...
# ※ uk-UA(ウクライナ語)が含まれていない点がポイント
アプリコード側でも同様に確認できます。
// UWP (C#)
using Windows.Media.Ocr;
using Windows.Globalization;
var langs = OcrEngine.AvailableRecognizerLanguages; // OCR として使える言語のみ列挙
foreach (var l in langs)
{
System.Diagnostics.Debug.WriteLine(l.LanguageTag); // 例: "en-US", "ja-JP"
}
// "uk-UA" がここに現れなければ、Ukrainian は OCR 非対応という判断ができます。
「UWP に言語パックを追加すれば良いのでは?」— できません
表示言語・入力言語の追加は UI/入力 のための機構です。OCR の可否は Language.OCR 系の Windows Capability に依存するため、UWP 側でパッケージ化しても反映されません。OcrEngine 単体でウクライナ語を動かす方法は現状ありません。
推奨される代替策(比較表)
| 代替手段 | タイプ | 対応言語 | 主な強み | 懸念点 | 適用シナリオ |
|---|---|---|---|---|---|
| Azure AI Vision OCR | クラウド API | 100+(ウクライナ語を含む) | 精度・版面耐性・更新速度、手書き/印刷混在も強い | ネット接続必須、従量課金、個人情報/持ち出し配慮 | ネット常時可、スケール重視、メンテをクラウドに委譲 |
| Tesseract + ukr.traineddata | オープンソース(ローカル) | 多数(ukr あり) | オフライン、カスタム辞書/再学習可能、コスト低 | 前処理必須、チューニングコスト、UWP への組込み工数 | オフライン要件、端末内完結、コスト最小化 |
| サードパーティ WinRT OCR | 商用 SDK(ローカル/オンプレ/クラウド) | ベンダー依存(uk 対応品あり) | UWP/WinRT 用 DLL やサンプルが充実 | ライセンス費用、更新/再配布の運用 | サポート重視、短納期、品質保証が必要 |
実装パターン(具体例とコード)
クラウド方式:Azure AI Vision OCR
最短でウクライナ語を実用投入したいならクラウドが手堅い選択です。UWP からは HTTPS 経由で呼び出します(セキュアに扱うため、キーやエンドポイントはサーバー経由で付与するプロキシ構成を推奨)。
処理フロー
- 画像を JPEG/PNG/PDF として用意(モバイルは 8MP 以上推奨)。
- 「読み取り(Read)」相当の機能に送信。
- 返却 JSON の言語タグ/座標/信頼度を解析しテキスト化。
- 大量処理はバッチ化・再試行・指数バックオフ・キャッシュで安定化。
UWP(C#)からの呼び出し例(シンプル版)
以下は概念を掴むための最小サンプルです。実運用では例外処理、タイムアウト、認証情報の安全な取り扱い、再試行・レート制御を追加してください。
using System.Net.Http;
using System.Net.Http.Headers;
using Windows.Storage;
// ※ 実運用ではキー/エンドポイントはバックエンドから取得してください
string endpoint = "https://{your-vision}.cognitiveservices.azure.com/";
string apiKey = "{your-key}";
// 画像ファイルを取得(例:ピクチャーから)
StorageFile file = await KnownFolders.PicturesLibrary.GetFileAsync("sample-ukr.png");
using (var stream = await file.OpenStreamForReadAsync())
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
var url = endpoint + "vision/v3.2/read/analyze?language=uk"; // 言語ヒント(自動判定でも可)
using (var content = new StreamContent(stream))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var res = await client.PostAsync(url, content);
// Read API は Operation-Location を返す(非同期ポーリング)
string operationLocation = res.Headers.GetValues("Operation-Location").FirstOrDefault();
// 簡易ポーリング
string resultJson = null;
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
var r = await client.GetAsync(operationLocation);
resultJson = await r.Content.ReadAsStringAsync();
if (resultJson.Contains("\"status\":\"succeeded\"")) break;
}
// JSON を解析して行ブロック・単語を抽出、テキスト連結へ
// (省略:実装では座標ソート・言語タグ uk の確認を行う)
}
}
ポイント:クラウドは SDK でも HTTP でも呼べます。最新版の SDK 名称やエンドポイントは進化が早いため、運用前に仕様書で確認し、API バージョニングの戦略(固定 or 追従)を決めましょう。
品質を上げる前処理 Tips
- 傾き補正(deskew)と二値化(Otsu/局所適応)
- 300dpi 相当(縦横 2480×3508 近辺)を目安にスケーリング
- コントラスト強調、ノイズ除去(median/bilateral)
- 文書境界の台形補正(透視変換)、余白トリム
オフライン方式:Tesseract(ukr.traineddata)
ネットワークに出せない要件では Tesseract の出番です。UWP 直接リンクには工夫が必要ですが、C++/WinRT の Windows Runtime Component としてラップすれば C# UWP から安全に呼び出せます。
ビルドと組み込み(概略)
- vcpkg で
tesseractとleptonicaを UWP 用トリプレット(例:x64-uwp)でビルド。 - UWP ソリューションに C++/WinRT の Windows Runtime Component プロジェクトを追加し、Tesseract をリンク。
- 学習データ
ukr.traineddataをtessdataフォルダーでパッケージに含め、初回起動時にApplicationData.Current.TemporaryFolder等へ展開。 - C# UWP からラッパーの公開メソッドを呼び出し。
C++/WinRT ラッパーの最小コード(概念)
// MyOcrBridge.idl
namespace MyOcrBridge
{
runtimeclass OcrService
{
OcrService();
String RecognizeText(Windows::Storage::Streams::IBuffer imageBuffer);
}
}
// OcrService.cpp(抜粋)
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
using namespace winrt;
using namespace Windows::Storage::Streams;
hstring OcrService::RecognizeText(IBuffer const& buffer)
{
auto reader = DataReader::FromBuffer(buffer);
std::vector<uint8_t> bytes(reader.UnconsumedBufferLength());
reader.ReadBytes(bytes);
// メモリから Pix を作成(詳細省略:入力は PNG/JPEG を想定)
Pix* image = pixReadMem(bytes.data(), (size_t)bytes.size());
tesseract::TessBaseAPI api;
// "ukr" を指定(英数字混在なら "ukr+eng" など)
if (api.Init(L"path\\to\\tessdata", "ukr")) {
pixDestroy(&image);
throw hresult_error(E_FAIL, L"Tesseract init failed");
}
api.SetPageSegMode(tesseract::PSM_AUTO);
api.SetImage(image);
char* out = api.GetUTF8Text();
hstring result = to_hstring(out);
delete[] out;
pixDestroy(&image);
api.End();
return result;
}
C# UWP から呼び出す例
using MyOcrBridge;
using Windows.Storage;
using Windows.Storage.Streams;
var file = await KnownFolders.PicturesLibrary.GetFileAsync("sample-ukr.png");
using (IRandomAccessStream s = await file.OpenAsync(FileAccessMode.Read))
{
var buffer = new Windows.Storage.Streams.Buffer((uint)s.Size);
await s.ReadAsync(buffer, (uint)s.Size, InputStreamOptions.None);
var ocr = new OcrService();
string text = ocr.RecognizeText(buffer);
// 認識結果を UI に反映
}
学習データの選び方
tessdata_fast/ukr.traineddata:軽量・高速だが精度は中程度。tessdata_best/ukr.traineddata:高精度だがメモリ/CPU 負荷が高い。- 英数字混在なら
"ukr+eng"のように複数指定可能。 - 辞書(user-words)やホワイトリスト(
tessedit_char_whitelist)で誤認識を抑制。
前処理・チューニングの勘所
- 解像度を 300dpi 前後に正規化。フォントが細い場合は少し拡大。
- 二値化+ノイズ除去(文書向けの Sauvola/Bradley など)
- 台形補正/傾き補正/余白除去で版面を安定化。
- PSM(ページセグメンテーション)を用途に合わせて固定(単一行/単一ブロック/自動)。
UWP での設計ガイド:選定の判断材料
| 要件 | 推し構成 | 理由 | 補足 |
|---|---|---|---|
| オフライン必須(閉域/機密) | Tesseract(C++/WinRT ラップ) | 端末内完結、コスト低、柔軟 | 初期チューニングが必要。画質前処理が鍵。 |
| スピード重視・多言語・メンテ最小 | Azure AI Vision | 精度/安定性/更新の外部化 | コストとレイテンシ管理、PII 取扱い設計が必要。 |
| サポートと SLA を重視 | 商用 WinRT OCR | ベンダー保守、導入が速い | ライセンス/再配布設計に注意。 |
フォールバック戦略(実装パターン)
「まず OcrEngine を使い、だめなら外部へ」の順序で段階的に適用する構成です。
using Windows.Media.Ocr;
using Windows.Globalization;
OcrEngine engine = null;
var target = new Language("uk-UA");
// 1) OS OCR がその言語をサポートしているか確認
bool supported = OcrEngine.AvailableRecognizerLanguages.Any(l => l.LanguageTag == target.LanguageTag);
if (supported)
{
engine = OcrEngine.TryCreateFromLanguage(target);
// 期待通りならこのまま使用
}
else
{
// 2) フォールバック:クラウド or Tesseract へ
// - クラウド可: Azure AI Vision
// - オフライン: Tesseract ラッパーを呼ぶ
}
こうしておくと、将来 Windows OCR が新言語を追加した場合でも、OS 側の対応を自動的に検出して活用できます。
セキュリティ・運用・コストの観点
クラウド(Azure AI Vision)
- 機微情報の扱い: 送信前にマスキング(氏名/住所/電話など)やトリミングを検討。TLS 終端・キー保護を厳格に。
- 課金管理: リクエストの冪等化、再試行の制限、バッチ処理でコスト/レイテンシを最適化。
- 可用性: リージョン冗長・サーキットブレーカ・フォールバック画像解像度の 2 段階戦略。
ローカル(Tesseract)
- 配布サイズ:
tessdata_bestは大きいため、必要言語のみ同梱。初回展開で遅延しない工夫を。 - ライセンス: Tesseract は Apache 2.0、フォント・辞書・学習データのライセンスも確認。
- パフォーマンス: ARM64 端末では NEON、x64 では AVX2 を活かすビルド設定を検討。
テキスト品質を最大化する 10 のチェックリスト
- 入力解像度は 300dpi 前後(スマホなら 8〜12MP)に統一。
- 強い影・ハイライトを避け、面照明を使う。
- 撮影時は真正面で、台形歪みを後処理で補正。
- 言語ヒント(uk / uk-UA)を与える。
- 辞書とホワイト/ブラックリストで誤認識を抑える。
- 数字/日付/金額など構造化データは正規表現で再検証。
- 改行・段落の再構成ロジック(読み順復元)を持つ。
- 低品質時の再撮影プロンプトを UI に組み込み。
- 品質ログ(解像度、傾き度、コントラスト)を残し A/B 改善。
- クラウドはレート・スロットリング・バックオフを実装。
サンプル:UWP プロジェクト構成(例)
Solution 'UkrOCR'
├─ App.UWP (C#)
│ ├─ Services
│ │ ├─ OcrFacade.cs // OcrEngine / Azure / Tesseract を抽象化
│ │ └─ ImagePreprocess.cs // 前処理(傾き・二値化)
│ ├─ Views / ViewModels
│ ├─ Assets
│ └─ tessdata (Content) // 初回起動時に Temp へ展開
├─ MyOcrBridge (C++/WinRT) // Tesseract ラッパー
│ ├─ OcrService.idl/.h/.cpp
│ └─ Native deps (tesseract/leptonica)
└─ Tests
└─ OcrQualityTests.cs
よくあるエラーと対処
| 症状 | 原因 | 対処 |
|---|---|---|
| 認識結果が常に空 | OCR 非対応言語/解像度不足/前処理不足 | 対応言語の確認、300dpi 化、二値化+傾き補正 |
| 海外文字が「?」や四角になる | 出力フォント未対応/エンコーディング問題 | UTF-8 固定・レンダリングフォントを Noto 系に |
| クラウドが時々タイムアウト | 一時的負荷/ネットワーク品質 | 指数バックオフ再試行、画像の段階的縮小、地域を近接化 |
| Tesseract 初期化失敗 | tessdata パス不正/ukr.traineddata 不足 | 起動時展開の成否確認、例外ログの追加 |
テストデータと評価の進め方
- 母集団の代表性: 実運用の用紙・フォント・スキャン条件を網羅した 50〜100 枚のセットを作る。
- メトリクス: 文字/単語正解率、エンティティ抽出の F1、再現率/適合率。
- ベースライン: まずはプレーンな前処理+デフォルト設定で測る。
- AB テスト: 前処理(deskew あり/なし、二値化方式)や PSM、学習データ(fast/best)を入れ替えて比較。
- 運用品質: 認識信頼度閾値で人手確認キューに回す運用ルールを用意。
法務・コンプライアンスの注意
- クラウド送信前にプロファイリング・本人識別につながる情報のマスキング方針を策定。
- ログには原本画像を保存せず、再現性に必要なメタ情報(解像度、処理パラメータ、ハッシュ)のみ保持。
- 学習データ/辞書のライセンスと出自を明確化。
今後の見通し
Windows 標準 OCR の対応言語はこれまで限定的に拡張されてきましたが、ウクライナ語の追加は公知のロードマップとしては確認できません。オフラインでのウクライナ語 OCR を組み込みたい場合は Tesseract かサードパーティ SDK、クラウドが許容できるなら Azure AI Vision が現実解です。将来的に OS 側の対応が拡充された場合に備え、OcrEngine.AvailableRecognizerLanguages を起動時に確認し、対応していれば自動的に切り替える構成にしておくとメンテナンスコストを下げられます。
まとめ
- UWP 標準の
OcrEngineはウクライナ語をサポートしていません。 - 表示/入力の言語パック追加では解決しません(OCR は別コンポーネント)。
- 代替は Azure AI Vision(クラウド) または Tesseract(オフライン)、要件に応じて選定。
- 将来の OS 対応に備え、ランタイムで対応言語を検出して自動切替できる設計がベストプラクティスです。
付録:コピペで使えるスニペット集
PowerShell:OCR 言語の一覧を CSV 保存
Get-WindowsCapability -Online `
| Where-Object { $_.Name -Like 'Language.OCR*' } `
| Select-Object Name, State `
| Export-Csv -Encoding UTF8 -NoTypeInformation -Path .\ocr_languages.csv
UWP(C#):OCR 可否を起動時にログへ
var tags = Windows.Media.Ocr.OcrEngine.AvailableRecognizerLanguages
.Select(l => l.LanguageTag);
string msg = "OCR languages: " + string.Join(", ", tags);
System.Diagnostics.Debug.WriteLine(msg);
// uk-UA が含まれるなら true
bool ukAvailable = tags.Contains("uk-UA", StringComparer.OrdinalIgnoreCase);
UWP(C#):クラウド/ローカルを自動フォールバック
public interface ITextOcr
{
Task<string> RecognizeAsync(SoftwareBitmap bmp, string langTag);
}
public sealed class OcrFacade : ITextOcr
{
public async Task RecognizeAsync(SoftwareBitmap bmp, string langTag)
{
var support = Windows.Media.Ocr.OcrEngine.AvailableRecognizerLanguages
.Any(l => l.LanguageTag.Equals(langTag, StringComparison.OrdinalIgnoreCase));
if (support)
{
var lang = new Windows.Globalization.Language(langTag);
var engine = Windows.Media.Ocr.OcrEngine.TryCreateFromLanguage(lang);
var res = await engine.RecognizeAsync(bmp);
return res.Text;
}
// 1) オフライン許可なら Tesseract
// return await _tesseract.RecognizeAsync(bmp, "ukr+eng");
// 2) それ以外は Azure Vision
// return await _azureVision.RecognizeAsync(bmp, "uk");
return string.Empty;
}
}
画像前処理:傾き推定(簡易版)
// OpenCV for UWP 等の利用を想定(概念コード)
double EstimateSkew(Mat gray)
{
var edges = gray.Canny(50, 150);
var lines = Cv2.HoughLinesP(edges, 1, Math.PI/180, 100, minLineLength: 100, maxLineGap: 10);
// 水平線の角度分布から平均を取り、傾きを推定して逆回転
// ...
return angle;
}
以上、UWP の OcrEngine ではウクライナ語は認識できないという前提に立ち、現場で即実装に移せる代替構成とサンプルをまとめました。要件(オフライン/クラウド、コスト、精度、開発速度)に合わせて適切な手段を選び、将来の OS 側の拡張に備えたフォールバック設計を入れておくのが実務的な最適解です。

コメント