![見出し画像](https://assets.st-note.com/production/uploads/images/27374480/rectangle_large_type_2_046411a26c2a423bf428b43d8add87a1.png?width=1200)
「ぬりカメWEBばん」の心技体、第二話「技」
こんにちは、はっきんぐパパです。
「ぬりカメ WEBばん」の第二話は「技」と題して、テクニカルなお話を書き留めたいと思います。
プログラムのお話になりますが、専門外の方も「へー、こんなことやってるのね」と、改めて「ぬりカメ WEBばん」を遊んでいただくときに、「ふむふむ」していただけるよう書ければと思います。
先に結論を申し上げると、すごく新しいことや難しいことをしたわけでなく、先人の肩に乗っただけです。
ぬりえの変換処理について
「画像をぬりえ化する」と聞いて、画像処理をちょっとだけ知ってる人は「ただの輪郭抽出でしょ?」と言います。輪郭検出はその名の通り、画像から輪郭部分を抽出する画像処理です。
中でも一番有名なCanny Edge法で輪郭抽出した結果をOpenCVの公式ドキュメントから借りてきました。
確かに、輪郭が抽出されていますが、服の中のシワなども抽出されているので、「ぬりえ」と呼ぶには細かすぎます。
困っていたところで、AI(機械学習、人工知能)の利用を思いつきます。画像を扱うAIの中に、セグメンテーションと呼ばれるタスクがあります。画像内の物体ごとに領域分けを行う技術で、車の自動運転などに応用されています。
セグメンテーションの一例として、ケンブリッジ大学のSegNetから画像を借りてきました。
車や道路、人間がちゃんと異なる色に分けられていて、どこにあるか、どんな形をしているかが認識できています。このセグメンテーションした後の画像から輪郭を抽出したらぬりえっぽくなるのではないか、と考えました。
調べていく中で、The Berkeley Segmentation Dataset and Benchmark、通称BSD500というデータセットがあることも知りました。
AIがセグメンテーションをきちんとできているか確かめるために、あらかじめ人間が領域分けを行った多種多様な500枚の画像で、非商業または教育目的であれば無償で利用することができます。
言うなれば、人力で作られた500枚のぬりえですので、これをもとに学習させてどんな画像が来てもぬりえを返せるAIを作ろうと考えました。
難しくなりすぎるので紆余曲折を省きますが、ハードウェアばんの「ぬりカメ 1号機」には2019年に発表された"Bi-Directional Cascade Network for Perceptual Edge Detection"(通称、BDCN)という論文をもとにしたAIを使っていました。
2019年に発表されただけあって、似たような他のAIモデルよりも優秀とされており、サーマルプリンタで384pxほどの画像を出力する1号機にとっては都合がよかったのですが、「ぬりカメ WEBばん」では家庭のプリンタで一番印刷しやすいA4サイズ(350dpi換算で横幅が2894px!)にしたかったので、より制御しやすい2015年発表の"Holistically-Nested Edge Detection"(通称、HED)をもとにした変換処理に切り替えました。
参考まで、BDCNの論文にHEDや他の手法と比較した画像がありましたので載せておきます。
このサイズ(1辺500px程度)だとBDCNの方がぬりえっぽいのですが、これを縦横6倍ずつ引き伸ばすとHEDの方がちょうど良くなるのがなんとなく分かっていただけるかと思います。
BDCNにしろ、HEDにしろ、線の太さが一様ではありません。1号機の時は「細線化」と呼ばれる太い線も1pxにする処理を加えていましたが、WEBばんではあえて省いています。
自分でぬりえを作るまで気づいてなかったのですが、市販されているぬりえにも塗りやすいものと塗りにくいものがあって、一番外側の輪郭だけ少し太い線になっていると、子どもの「ぐちゃっ」とぬりえでもミスがカバーされやすいんですね。
また、私が調べた限りでは細線化処理は再帰的なアルゴリズムが多く、2894px正方の画像で2,3分待たされてしまうこともザラにあったので、WEBばんではユーザ体験を重視して省きました。
ソースコードの方には細線化のプログラムも残してあるので、ご興味ある方は覗いてみてください。
WEBアプリケーションについて
第一話「心」でも書いたとおり、「ぬりカメ WEBばん」には開発当初からいくつかの要件がありました。
・完全無料、広告もつけない、稼働費はあとで考える
・アップロードの心理的抵抗をなくすべく、画像は一切保存しない
・全国のパパたちが自分で動かせるように、ソースコードも公開しよう
そしてなにより、「1秒でも早くローンチ」。
ハードウェアばんの1号機はRaspberry Piで動いていたため、シャッターボタンやプリンタの制御などもあって、大部分がPythonで書かれていました。
1秒でも早くローンチさせるにはこのPythonで書かれた部分をなるべく多く流用するのが肝となります。
次に、全国のパパたちがデプロイする可能性もあるならば、モノリシックな構造になっている方が良いだろうと考えました。時代のトレンドはマイクロサービスですが、「自分の息子/娘のためだけに」動かすならばなるべく簡単な構造になっていて、お家で眠っているPCでもすぐに動かせた方が良いだろうと思いました。
「稼働費はあとで考える」とはいえ、趣味の集まりのはっきんぐパパは無収入ですので、節約できるところはしたい。
一方で、A4サイズに向けて2894px正方の画像を扱うとなるとピクセル数ではFull HD(1920x1080)の約4倍にもなるので、それなりのメモリが必要になります。
上記を踏まえて、選択したのはGoogle App Engineです。
Google App EngineはPython3を標準でサポートしていて、負荷に応じて最大CPU2.4GHz、RAM2GBのインスタンスを勝手にスケールしてくれます。デプロイもお手軽で、テスト環境を別に作ることも容易ですし、さらにCDNや監視系もついてくる、ハンバーガーにドリンクとポテトだけでなくおもちゃもついてくるハッピーセットのような存在です。
経験上、AWSより安価で、急なアクセス増にも強い印象があります。
Google App Engineを土台に、骨組みはFlaskを使うことにしました。
今回はユーザ認証やデータベースとの接続がないと分かっていたので、なるべくシンプルなフレームワークが良かったのですが、最終的にたった1ファイル、140行程度で書き上がったのを見て、改めてFlaskが好きになりました。
「画像は一切保存しない」を達成するために、アップロードから生成までオンメモリで行うようにしました。それ自体は難しくなかったのですが、画像を保存できる条件だったならCloud TasksやCloud Functionsを使った分散処理にしていたと思います。
フロントエンドとデザインについて
フロントエンドはAlpine.jsとBulma CSSを採用しました。
スマートフォンからの利用が圧倒的に多いだろうと踏んでいたので、SPAが作りやすいフレームワークを使いたいと思いましたが、VueやReactは大袈裟だったので、新進気鋭のAlpine.jsを使ってみました。
初めて触ったAlpine.jsでしたが、日本語のドキュメントもありますし、Bulma CSSのようなCSSオンリーのフレームワークと相性が良くて大変助かりました。
Alpine.jsのおかげもあって、とても軽量な構成になったので、PWAにもこっそり対応しました。と言ってもService WorkerやLocal Storageを使うあてもないので、A2HSなmanifest.jsonを用意しただけですが。
「ぬりカメ WEBばん」を気に入ってくださった方はぜひスマートフォンのホーム画面に追加してもらえたら嬉しいです。
デザインについて、一番最初のワイヤーフレームが残っています。
第一話「心」で「一時、チーム内が喧々轟々」と書きましたが、揉めたのはデザインです。
諸事情あって、デザインチームより開発チームの方がどんどん先に進んでしまい、デザイン指示のないことを良いことに、開発チームの都合の良い解釈で「ルビを振ろう」「1ページで完結させよう」「ローディングもいるよね」と勝手に進めて、終盤になって「それならこうしたい」がドカーンと降ってきたのです。
(Slackのログを見返すと、4/19にドカーンとなっているので、主だった開発は1週間で終わってて、デザイン修正に2週間かかったんですね…)
今から思えば、これが急に露わになったはっきんぐパパの弱点でした。
はっきんぐパパはそれぞれが本業あっての有志の集いのため、各々が割けるリソースに違いがあります。そんな中、余裕のある人間が、今回の場合は開発チームがデザインやプロジェクト管理、バグ管理まで踏み込んでやっていたのでした。
ある一部の人だけが踏み込みすぎたり、やりすぎてしまうことによって、「餅は餅屋」問題が起きるだけでなく、当事者以外には置いてけぼり感すら感じさせてしまいます。
外出自粛下で、顔を合わせる機会が減っていたことも一因です。また、自粛下でなくとも、リモートワークが主体のチームにはいつでも起こりえた問題だったとも言えます。
「ぬりカメ WEBばん」のローンチ後、これはチームの構造の問題だとして、互いのリソースを上手に共有するためのGItHub勉強会などを開催し、今まで以上に密にコミュニケーションを取っています。
また、各自のリソースに差があることは弱点でもありながら、最大の強みでもあります。
以前と変わらず、自分の本業ではないことにも挑戦するのを是とする雰囲気があります。
はっきんぐパパの中にいろんな専門家がいるので、「電子工作はじめてみたい」「動画の編集してみたい」と思った時に身近に師匠がいるのは本当にありがたいです。
今回はWebサービスを作りながら技術面以外にも学びがありました。
今後も弱みと強みを活かして、いろんな挑戦をしていきたいと思います。
末筆ながら、「ぬりカメ WEBばん」を開発するにあたって、参考にした記事や論文、ライブラリは数え切れないほどたくさんあります。
溜め込むよりもどんどん共有していくエンジニアイズムが世界中に浸透していることに毎日感銘を受けます。
ひとりひとりに謝辞を伝えられたら良いのですが、今回、私たちのソースコードも公開して、どこかの誰かの助けになってくれたら僥倖です。
いただいたサポートは、今公開しているサービスの維持や、これからの子供のためのものづくりに活用させていただきます!