最近OCRモデルを自作していて、OCRの学習データを生成するために SynthText という手法を使用しました。SynthText はメンテもされていない古めの技術で、動かすのにやや手間取ったので、備忘録がてら共有です。
SynthTextとは?
SynthText は、背景画像にテキストを自然合成するための手法です。
深度とセグメンテーション情報を持つ背景データを使い、任意のフォント・文字を背景に溶け込むように合成します。
この手法は 2016 年、Oxford 大学の Ankush Gupta らによって提案されました。
CVPR 2016
SynthTextの現状
SynthText のソースは、Githubのリポジトリとして2016年から公開されています。
当時主流だった Python 2 で実装されており、Python 3 ブランチもあることにはあるのですが、それももう5年以上は更新が止まっており、最新でもPython 3.6 前提です。
言うまでもなく 3.6 も古めで、近年の macOS では 3.6 のビルドが詰まりやすい状況です。私の環境で pyenv で Python 3.6 を入れようとしたところでは、zlib あたりのエラーが出て、サクッとセットアップとはいかなさそうでした。
なぜ今SynthTextなのか
SynthText がすでにあまりメンテされていないのは、単純に需要が少ないからでしょう。
最近のOCRトレーニングでは、公開されているリアルな実写データセットを使うのが一般的で、わざわざデータを自作する必要はあまりありません。
ただ、今回私が扱う文字体系はマイナーすぎて実写データが存在しないため、合成によるデータ生成が不可欠でした。
類似ツールとして、3D空間に文字を配置してレンダリングする SynthText3D / UnrealText もありますが、私が欲しいのは実写ベースの合成であり、これらはその用途とは異なります。なによりセットアップ・実行が重量です。
そういった理由では、軽量で実写ベースのデータセットを大量に生成できる SynthText はまだまだ現役です。
SynthText-docker の使い方
Python 3.6 は古くセットアップでエラーが発生しやすいです。エラーを1つずつ修正していくのも一つの手ですが、ライブラリのバージョン違いなどによる副作用も避けたいので、本家リポジトリをフォークし、当時そのままの環境で動く SynthText-docker を作りました。
セットアップ
前提: Docker が利用可能であること。
git clone git@github.com:ShimeiYago/SynthText-docker.git
cd synthtext-docker
# ビルド
docker-compose build
簡易実行テスト
本実行前に、少量のサンプルで、画像生成が期待通りに動作するかを確認します。
初回のみサンプル素材データ (約56MB) のダウンロードが発生するので少し時間がかかります。
docker-compose run --rm synthtext python gen.py
これで results/SynthText.h5 が生成されるはずです。
生成された .h5 ファイルはそのままでは中身が確認できないため、内容を可視化する場合は次のコマンドを実行します。
docker-compose run --rm synthtext python visualize_results.py
大規模素材データ準備
先の簡易実行テスト時にダウンロードされた素材データはあくまでサンプルで数が少ないため、実用的なデータセットを生成するには、もっと大量の背景データが必要です。
論文では、事前に深度とセグメンテーション情報を付与された8,000の大規模背景データが使用されました。
1) 背景データの入手(ミラー / torrent)
8,000の大規模背景データについて、当時はダウンロードリンクが存在しましたが、今はもうリンクが切れています。これも SynthText の現代での使用を難しくしている要因の一つですね。
幸いなことに、Academic Torrents にミラーがあり、公式からもここからダウンロードするように案内があります。
必要なファイルは bg_data/bg_img.tar.gz(約 8.9GB)、bg_data/depth.h5(約 15GB)、bg_data/seg.h5(約 6.9GB)、bg_data/imnames.cp(背景テキストを含まない画像名リスト)の 4 つです。ダウンロード後は次のように配置します。
downloads/
└─ bg_data/
├─ bg_img.tar.gz
├─ depth.h5
├─ seg.h5
└─ imnames.cp
注意: 画像の著作権は各権利者に帰属します。ライセンスや利用範囲は各自で確認してください。
2) 画像アーカイブの展開と h5 へのパッキング
# 画像アーカイブを展開
mkdir -p downloads/bg_data/bg_img
tar xf downloads/bg_data/bg_img.tar.gz -C downloads/bg_data
# 素材を単一 .h5 に統合
docker-compose run --rm synthtext \
python pack_bgdata_to_h5.py -i downloads/bg_data -o data/dset_big.h5
これで大規模用の全素材が data/dset_big.h5 に統合されたはずです。
3) フォントの追加(任意)
独自のフォントを利用したい場合は、任意のフォントファイル .ttf または .otf を data/fonts/ 配下に配置してください。
その後、data/fonts/fontlist.txt を編集してフォントファイルへの相対パスを記載し直します。
忘れてはならないのが、サイズ変換モデルを再生成することで、フォントファイルを更新するたびにこれを実行する必要があります。
# フォントに合わせてサイズ変換モデルを再生成(図も保存)
docker-compose run --rm synthtext \
python invert_font_size.py --viz
上記コマンドを実行後は、念のためフィットの診断図 results/font_model_plots/ を確認してください。
measured h(y)が linear fit に一致していればOKです。
データセット生成実行
大規模素材データの準備が終わったので、いよいよデータセットを生成していきます。
以下のように、先ほど統合した大規模素材データ data/dset_big.h5 を指定して、データ生成を開始します。
docker-compose run --rm synthtext \
python gen.py --db_path data/dset_big.h5
時間がかかるので気長に待ちましょう。
(任意)行レベル BBox を付与
ちなみに、オリジナルの SynthText には無かった機能ですが、上記コマンド実行時、--line_bb オプションをつけることで、行レベルのアノテーションも付与できるように追加開発しておきました。
docker-compose run --rm synthtext \
python gen.py --db_path data/dset_big.h5 --line_bb
従来の SynthText で付与される charBB / wordBB に加えて、 lineBB も同時に付与されるようになり、行単位の検出訓練データを作れるようになります。
このオプションを追加したのは、私がOCRモデルを自作する際に利用したフレームワーク PaddleOCR が、データセットとして行単位のアノテーションを推奨しているからです。
可視化
最初にサンプルを生成した時と同様に、生成されたデータは .h5 形式のファイルにまとめられていて、そのままでは中身を可視化できません。
生成がうまくいっているか確認するために、以下コマンドで数枚内容を可視化しておくと良いでしょう。
# 通常可視化
docker-compose run --rm synthtext \
python visualize_results.py
# lineBBを可視化(--line_bb で生成した場合)
docker-compose run --rm synthtext \
python visualize_results.py --line_bb
(任意)PaddleOCR 検出形式へのエクスポート
.h5 形式は、多くのOCRフレームワークにとっては一般的な形式ではありません。
見やすい形式へとエクスポートするスクリプトを追加しておきました。
もしOCRモデルのフレームワークとして PaddleOCR を選択するなら、このスクリプトの出力がそのまま利用可能です。
# word 単位のアノテーション
docker-compose run --rm synthtext python export_to_paddleocr.py \
-i results/SynthText.h5 \
-o results/paddleocr_data
# 行単位のアノテーション(--line_bb で生成した場合)
docker-compose run --rm synthtext python export_to_paddleocr.py \
-i results/SynthText.h5 \
-o results/paddleocr_data \
--line_bb


