先日「Aurebesh Scanner(オーラベッシュ・スキャナー)」というサービスをリリースしました。
このサービスは、スターウォーズの世界で使用されている標準的なアルファベット「Aurebesh(オーラベッシュ)」に特化したOCRで、世界初の、Aurebeshに対応した誰でも利用可能なOCRサービスになります。
用途
主にディズニーのテーマパークにおいて、Aurebeshを数多く目にすることができます。
例えば東京ディズニーランドにあるアトラクション「スター・ツアーズ」だけでも、以下のようなAurebeshで書かれた看板や表記が目に入ります。
しかし東京は少ない方で、カリフォルニアやフロリダのディズニーにあるスターウォーズのテーマエリア「ギャラクシーズ・エッジ」では、さらに多くのAurebeshを目にすることができます。
これらの文章は、アトラクションやエリアのストーリーを理解するために重要となりますが、まず読めないため、完全に暗記するか、対応表を持ち歩く必要があります。
実際に「ギャラクシーズ・エッジ」では、以下のような「Aurebesh対応表キーホルダー」が販売されています。
今回開発したようなAurebesh対応OCRがあれば、Aurebeshの知識がない人や対応表を持たない人でも素早くAurebeshを解読することができます。
手法
スターウォーズがいくらビッグコンテンツとはいえ、Aurebeshの公開OCRモデルは存在しません。よって自作するしかありません。
ここからは、どのようにしてOCRモデルを自作したか説明していきます。この手順自体は、Aurebeshに限らずどんな文字にも共通して適用できるものなので、もしマイナー文字などのOCRを自作する必要がある場合は同じ方法でいけるはずです。
データセット作成
Aurebeshはマイナーなため、公開データセットすら存在しません。よって自前でデータセットを用意する必要があります。
OCRの仕組みは様々ですが、今回私が採用するdetector-recognizer方式では、detector(画像から文字の存在する領域を検出するモデル)とrecognizer(検出された文字領域の画像から、実際の文字列を読み取るモデル)の二つのモデルをトレーニングします。よって、データセットもdetector用とrecognizer用のニ種類を用意する必要があります。
実写ベースのデータセットがあればそれがベストなのですが、前述の通りそんなものは存在しませんし、自分で大量の写真を集め、それにラベリングしていくのは途方もない時間がかかります。
よって今回はデータセットを合成しました!
OCRのモデル学習では、データセット不足を合成データで補うことは珍しくありません。
データセットを合成するために、今回は以下のPythonライブラリを使用しました。
| データセットの種類 | 使用ライブラリ | 生成枚数 | サンプル |
|---|---|---|---|
| Detector用 | SynthText | 8,000枚 (train: 6,400 / val: 1600) |
![]() |
| Recognizer用 | SynthTIGER | 300,000枚 (train: 240,000 / val: 60,000) |
![]() |
SynthTextは割と古い技術でそのままでは動かないので、実行する場合は私が以前に書いた記事を参考にしてください。
最終的に生成したデータセットは以下のようなディレクトリ構成でまとめておきます。
aurebesh/
├── det/
│ ├── train.txt
│ ├── val.txt
│ └── images/
└── rec/
├── train.txt
├── val.txt
├── dict.txt
└── images/
Detector側のアノテーションファイル train.txt / val.txt は、以下のような形式にしてください。
(1行につき1画像。{画像パス}と{アノテーション}をタブ区切りで記述します)
images/aaa.jpg [{"transcription":"could they","points":[[221,367],[328,306],[334,315],[226,376]]},{"transcription":"or it","points":[[177,331],[238,292],[244,301],[182,340]]},{"transcription":"the","points":[[240,341],[278,315],[286,327],[249,353]]},{"transcription":"it can","points":[[105,28],[249,28],[249,64],[105,64]]}]
images/bbb.jpg [{"transcription":"life","points":[[272,255],[313,212],[329,227],[289,271]]},{"transcription":">us","points":[[303,293],[339,264],[356,285],[321,314]]},{"transcription":"AUDIO LETTER","points":[[253,255],[333,169],[343,179],[263,265]]},{"transcription":"other","points":[[31,111],[104,145],[96,160],[24,126]]},{"transcription":"John","points":[[257,301],[312,246],[331,265],[276,321]]},{"transcription":"the","points":[[149,223],[252,233],[250,249],[148,238]]},{"transcription":"the","points":[[154,243],[257,254],[255,270],[152,259]]}]
一方で、Recognizer用の側のアノテーションファイル train.txt / val.txt は、以下のような形式にしてください。
}
(1行につき1画像。{画像パス}と{文字列}をタブ区切りで記述します)
images/1/1234.jpg IPAD
images/1/5678.jpg IVORY SANG
最後に dict.txt は、Recognizer が出力可能な文字の集合(辞書)を定義するファイルです。
1行につき1文字を記述し、このファイルに含まれる文字のみが、認識結果として出力されます。
英大文字・数字・記号など、Recognizer に認識させたい文字をすべて列挙してください。
今回は以下のように、 ラテン文字(A–Z)+数字+一部記号 を対象にした dict.txt を使用しました。
!
&
'
,
-
.
0
1
2
3
4
5
6
7
8
9
A
B
C
...
Z
PaddleOCRセットアップ
今回はOCRのフレームワークとして PaddleOCR を使用しました。
PaddleOCR は学習済みモデルや実装例が豊富で、モデルのカスタマイズを前提としているライブラリであるため、今回のようなマイナーフォントを使ったOCRを作る用途に適していました。
また、今回私はCPUでも動作するレベルの軽量なOCRモデルを求めており、PaddleOCR は、高性能モデルの他に、軽量なmobile系モデルも提供していたことから、私の意図にピッタリでした。
以下のドキュメントに沿って、PaddleOCRをlocalにセットアップしてください。
https://www.paddleocr.ai/main/en/version3.x/installation.html
モデルトレーニング
今回、PaddleOCRが提供する軽量な学習済みモデルに Aurebesh のデータセットを追加で学習させることで、ファインチューニングを行なっていきます。これによって、文字のエッジ形状といった汎用的特徴を捉えた学習済み重みを引き継ぐことができ、学習が早く収束することを期待できます。
なお、今回ファインチューニングのベースに用いたモデルは以下の通りです。
| モデルの種類 | モデル名 |
|---|---|
| Detector用モデル | PP-OCRv5_mobile_det |
| Recognizer用モデル | en_PP-OCRv5_mobile_rec |
どちらも PaddleOCR が提供する中で最新バージョンの v5 の中で、mobile系の軽量モデルを使用しています。
また、学習環境は以下の通りです。
| 項目 | 内容 |
|---|---|
| 環境 | AWS EC2 |
| インスタンス |
g6.xlarge(GPU) |
この環境は NVIDIA L4 GPU を搭載していて、比較的低コストでモデルの学習を行うことができます。
Detectorトレーニング
基本的には以下のチュートリアルに沿って、Detectorモデルのトレーニングを実施します。
https://paddlepaddle.github.io/PaddleX/3.3/en/module_usage/tutorials/ocr_modules/text_detection.html
パラメータは下記の通りで、これ以外は PP-OCRv5_mobile_det の設定そのままです。
| 項目 | 内容 |
|---|---|
| ベースモデル | PP-OCRv5_mobile_det |
| データセット数 | 8,000 (train: 6,400 / val: 1600) |
| エポック数 | 62 |
| バッチサイズ | 8 |
学習の推移は以下の通りで、最終的にevalデータに対するHmeanが 0.84 まで向上しました。
ベースモデルは元から文字領域を検知できるようにトレーニングされていたため、1ステップ目から 0.8 近いhmeanが出ていることが特徴的です。ファインチューニングによってそれが少し向上して 0.84 までいったことがわかります。
Recognizerトレーニング
基本的には以下のチュートリアルに沿って、Detectorモデルのトレーニングを実施します。
https://paddlepaddle.github.io/PaddleX/3.3/en/module_usage/tutorials/ocr_modules/text_detection.html
パラメータは下記の通りで、これ以外は PP-OCRv5_mobile_det の設定そのままです。
| 項目 | 内容 |
|---|---|
| ベースモデル | en_PP-OCRv5_mobile_rec |
| データセット数 | 300,000 (train: 240,000 / val: 60,000) |
| エポック数 | 6 |
| バッチサイズ | 160 |
学習の推移は以下の通りで、最終的にevalデータに対する正答率 (完全一致) が 0.97 まで向上しました。
Detector は学習前から文字領域をある程度検出できましたが、Recognizer は Aurebesh が未知の文字体系のため、Accuracy は 0 からのスタートでした。
それでも学習を進めるにつれて Accuracy は着実に向上し、最終的に 1.0 近くまで到達しました。
性能テスト
以上のトレーニング済みモデルを使って、私が撮影した実際の写真を対象に性能を検証しました。
成功例
アトラクション「スター・ツアーズ」の案内板
ほぼほぼ正解ですが、右下の「GATES 1 THROUGH 6」だけ、数字の「1」を誤認識しています。
とはいえ、数字の「1」と Aurebesh の「I」は形が完全に同じなので、ここはある程度仕方ないかなと思っています。
アトラクション「スター・ツアーズ」出口の看板
「ギャラクシーズ・エッジ」エリアにあるゴミ箱
アトラクション「ミレニアム・ファルコン: スマグラーズ・ラン」の看板たち
概ね問題ないのですが、一部、通常のアルファベットを Aurebesh と誤検出してしまっていますね。
アトラクション「ミレニアム・ファルコン: スマグラーズ・ラン」の待機列
「ギャラクシーズ・エッジ」エリア内のゴミ箱風オブジェクト
「警告:サルラックが消化中です。しばらくお待ちください」と書かれていることがわかります。
ドロイド用 Aurebesh
通常の Aurebesh とは形が異なる「ドロイド用Aurebesh」にも対応できていますが、やや精度は落ちるようです。
手書き Aurebesh
学習データは全てフォントを使った合成画像なので、手書き文字は含まれていませんが、かなり綺麗な書き方をされていれば、手書き文字でも正確に認識が可能です。
失敗例
アトラクション「スター・ツアーズ」の電子ボード
この電子ボードは、撮影角度や距離には関係なく、うまく動作しませんでした。この電子ボードは文字の後ろに複雑なパターンがあり、これがOCRの Detection / Recoginition 処理を阻害していると思われます。
凹凸文字
印字されたものではなく、立体的に文字が書かれている凹凸文字については、うまく読み取れないケースが多かったです。
おわりに
一旦、実用的なサービスとして形にはできましたが、OCRとしての精度はまだ改善の余地があります。
とはいえ「Aurebesh対応のオープンなOCRサービス」は、世界的にも初めてなはずで、まずは“動くもの”を世に出すことに意味があると考えました。
今後も改善を進めていきます。






















