以前、 mashabow さんが、紙に書いた手書きの文字から手書きフォントを自動で生成する、という試みをしていた。
てきとうに書いて作ったフォント - しろもじ作業室
これが2008年のことである。当時この自動生成についての動画を見て感激した覚えがある。そして、更に自動化を進めたシステムが使えればいいのになあと思っていたが、実装する技術力はそのときの自分にはなかった。
一方それから8年近く経って(そんなに前なのか…)、今なら時間もあるし、それを実現する技術力もついたかなあと思ったので、作ってみた。縛りとしては、動作にあたって有料のソフトを必要としないというものである。
フォント作成の流れ
1. 書き込みフォームをつくる
フォントにしたい文字のリストをつくる。
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろ わゐゑをんがぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽぁぃぅぇぉゃゅょっゎ アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロ ワヰヱヲンガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポァィゥェォャュョッヮヵヶヴ ゝゞヽヾ゛゜ー、。,.・…‥〜&:;?!※〒〃々〆〇仝〓―‐/\ ‘’“”()〔〕[]{}〈〉《》「」『』【】 ♪☆★○●◎◇◆□■§△▲▽▼¶→←↑↓ ̄_†‡
みたいな感じで。これをテキストファイルに保存し(list.txt)、次のように python スクリプトを実行する。これにより文字を書き込むための書き込みフォームを生成する。
python3 handfontgen/formgen.py -o zenkaku.pdf list.txt
するとこんな感じのPDFができあがる。
次のリンクから生成されたPDFが見られる。
2. 印刷して書き込む
1. で作ったPDFを印刷し、薄い青色の四角の中に文字を書き込む。
書き込んだ後はスキャンして画像データとして取り込む。
取り込んだデータはこんな風である。
フォント生成スクリプト
スクリプト本体や必要なデータファイル、サンプル類をまとめて Github に上げた。
github.com
インストール・実行方法
ここでは Ubuntu にインストールして実行する方法を示す。開発自体は Windows 7 の Cygwin を使って行っていたので、 Windows でも動くと思うが特に解説はしない。
ソフト・ライブラリのインストール
端末を開いて、
sudo apt update sudo apt upgrade sudo apt install fontforge potrace zbar-tools libcairo2-dev python3-numpy \ python3-cairosvg python3-pypdf2 python3-pip libffi-dev pip3 install qrcode
OpenCV3のインストール
必要なパッケージをインストール。
sudo apt install libopencv-dev build-essential checkinstall cmake pkg-config \ yasm libtiff5-dev libjpeg-dev libjasper-dev libavcodec-dev libavformat-dev \ libswscale-dev libdc1394-22-dev libxine2-dev libgstreamer0.10-dev \ libgstreamer-plugins-base0.10-dev libv4l-dev python3-dev python3-numpy \ libtbb-dev libqt4-dev libgtk2.0-dev libfaac-dev libmp3lame-dev \ libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev \ libxvidcore-dev x264 v4l-utils git
git clone https://github.com/Itseez/opencv.git cd opencv git checkout 3.1.0 mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D BUILD_opencv_java=OFF -D WITH_IPP=OFF \ -D PYTHON_EXECUTABLE=/usr/bin/python3.4 .. make sudo make install sudo sh -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf'
これにて必要なもののインストールは完了。
Github からフォント生成用のコードをとってくる
cd ~
git clone https://github.com/nixeneko/handfontgen.git
実行
ダウンロードしたフォルダに移動する。
cd ~/handfontgen
以下、カレントディレクトリが ~/handfontgen であるとする。
テキストファイルから書き込む用のPDFファイルの作成
PDF ファイルを生成する。サンプルデータとして使ったPDFの生成は次のようなコマンドを実行するとできる。
python3 handfontgen/formgen.py -o zenkaku.pdf sampledata/list_kana.txt sampledata/list_kigou.txt python3 handfontgen/formgen.py -o hankaku.pdf -t resources/charbox_template_5-8-5_5-4-5.svg sampledata/list_ascii.txt python3 handfontgen/formgen.py -o testkanzi.pdf sampledata/list_kanzi-test.txt
出力されたものが sampledata/pdf/ 以下に入っている。出来上がったPDFを印刷し、文字を書き込む。
スキャンした画像からフォントを生成する
サンプルとして、書き込んだ画像を sampledata/scanned_300dpi/ 以下に用意した。
サンプルのフォントを生成するには次のコマンドを実行する。
python3 handfontgen/fontgen.py -m sampledata/fontmetadata.xml tekitou.otf sampledata/scanned_300dpi/
これでしばらく待つと tekitou.otf が生成される。生成されたものが sampledata/otf/tekitou.otf である。
また、上ではSVGファイルを一時ファイルとして書き出しているのだが、文字を追加する際にいちいち全てを書き出していると時間がかかる。スキャン画像からフォントを生成する処理は、
の2つの処理に分けることができる。これだと追加があった文字だけを処理できるので時間の節約になる場合がある。
python3 handfontgen/scanchars.py glyphs/ sampledata/scanned_300dpi/ python3 handfontgen/fontgenfromsvg.py tekitou.otf glyphs/ sampledata/fontmetadata.xml
出力されるフォントについては上の場合と変わらない。
何をやっているのか?: 自動生成の原理
0. 書き込みフォームの生成
四隅のマーカーが乗ったSVGの上に、一文字分の領域(これは別のSVGファイルで定義されている)を並べていく。
この際、指定された文字のリストから一文字ずつ文字を書き込み文字コードデータのQRコードを埋め込んでいる。さらに右下には一文字分の領域にマーカーで指定された部分の領域情報についてのQRコードを埋め込む。一ページ分ができたらPDFに変換する。これを指定された文字のリストが空になるまで繰り返す。
最後にPDFを1つのファイルにまとめる。
なお、文字幅についてはページごとのQRコードで指定しているため、半角と全角など幅がことなる場合にはシートを分ける必要がある。
2. 1文字ずつに分割
- 左端と上端にあるマーカーの黒い部分を抽出し、そこで1文字分ずつに分割する。
- フォーム右下端にあるQRコードを zbar で読み取り、文字が書かれる領域のサイズを取得する。
3. 文字をSVGにする
1文字ずつの領域に切り分けられたそれぞれに対して処理を行う。
所感
- 今回は、サンプルとしてアップロードする画像ファイルを軽くしたかったので、300dpiでスキャンした画像を使用したが、 8×8mm は300dpiだと 94×94px であり、フォントの 1000×1000 のメッシュに比べると解像度が粗い。 600dpi でも試したが問題なく動いているようだった。フォントで表現できる最大の解像度でスキャンしようとすると 3200dpi 位となり、ファイルサイズはかなりの大きさになりそう。そこまで大きなものは試してないので動くかわからないが。
- マーカー乗っけたりQRコード埋め込んだりしてるのは、最初に書き込みフォームの形を決めうちしたくなかったため、後工程で情報が取り出せるように埋め込んだというもの。
- 一文字分の領域のテンプレートとなっているSVGファイルを編集すれば、文字を書く領域を別のサイズにした書き込みフォームが作れる。ただこのSVGファイルが72dpi基準で作られている(Adobe Illustrator)ので、Inkscape(90dpi)とかで編集しようとすると面倒そう。
- 手書き文字を、特にアルファベットにおいて、同じ幅で並べるといささか奇妙に思える。プロポーショナルな出力ができるようにしたらよいのかもしれない。
- ゴミに弱い。スキャン時についたゴミはフォントにそのまま残ってしまうので、SVG生成に回す前にゴミとりをしないといけない。ゴミとり機構を乗せるといいのかもしれない。
- こうして作ったフォントをみるとベースラインがきれいに並ばないので、不恰好である。書き込みフォームにベースラインの表示を入れてもいいかもしれない。
コマンド一発でフォントが出来上がるとなんだか有りがたみがない……。