目からビームな画像を生成するWebサービスを作った

ももいろクローバーZのニューシングル「Z女戦争」が6月27日に発売されます。

Z女戦争(初回限定盤A)(DVD付)

Z女戦争(初回限定盤A)(DVD付)


で、それに先立って公開された新衣装でのアー写が、何故かメンバーが目からビームを放っているものだった。

ももクロ「いいとも」テレフォンショッキングに再び登場 - 音楽ナタリー


これに影響を受けて、周りのももクロクラスタの方々が次々にTwitterの自分のアイコン画像を加工して目からビームを放っているものに変更していたりしたのだけど、それなりに画像を加工するツールやテクニックがないと難しいし、手間もかかる。「もっとカジュアルに目からビームを放ちたい!」という需要もあるのではないかと思い、自動で加工し「目からビーム画像」を生成するWebサービスを作ってみた。

画像URLの指定、画像ファイルの直接アップロード、もしくはTwitter OAuthログインによって取得する自分のアイコン画像、を対象にして自動で目の辺りからビームを放った画像を生成する(ただし顔が検出できれば)。

herokuで公開している。リポジトリは以下に。

顔認識

画像から顔認識して目の位置を割り出すことさえできればどうにかできるはず、と思って思い浮かんだのは"miyagawanize"で使われていたOpenCVだったのだけど、コレをサーバにインストールしてWebサービスから使うのは若干めんどくさそう、もっと他に簡単なのないかな、とググっていたら「顔検出WebAPI」があることを知った。
kaolabo.com - 
コレを使うと、画像データもしくはURLを投げるだけでその画像内における顔の位置とその中の両目の位置を座標で返してくれる。まさに求めていた要件にピッタリだったので、これを利用することにした。
検出結果はXML形式で返ってくるけど、それほど複雑な内容ではなかったのでrexmlでparseして使った。

画像変換

できればサイズやフォーマットに制限なくどんな画像でも加工の対象になるようにしたい。けれどユーザはPNGJPEGか、どんな大きさの画像を上げてくるか分からない。しかも顔検出WebAPIは"jpegである必要がある"とのことなので、どうしてもリサイズとフォーマットの変換は必要になる。
herokuaddonにはBlitlineというのがあることを教えていただいた。

Blitline - Image processing in the cloud
確かにコレを使うとリサイズやjpegへの変換がWebAPIから可能なようだ。変換対象の画像URLを指定してjobを投げるとAmazon S3上のURLを返してくれて、数秒も待つと変換後の画像がそこに上がる。便利。
(でも結局RMagickでも出来そうだったのでBlitlineは使わないことになった。機会があったらまた触ろうと思う。)

画像加工

画像をリサイズしてフォーマット変換して、顔検出APIから目の位置の座標を得ることができれば、あとはその位置から直線を引けばビームが描ける。
画像に対する描画、加工などはそれなりのライブラリが欲しい。PerlだったらImagerだと思うのだけど、heroku上でRubyでやろうとするとどうやらRMagickというのが使えるらしい。
RMagick Download Page
下記の記事などを参考にimagemagick, RMagickをインストール。
http://d.hatena.ne.jp/ruedap/20110410/ruby_heroku_use_rmagick_bundler_require
Blitlineでやろうとしていたリサイズや変換などもコレを使って出来てしまったので直線の描画まで含めて加工はすべてRmagickにやってもらうことにした。

ビーム

顔の向き、視線の向きから適切な方向にビームを放ちたかったけど、なかなか難しく。検出された顔の中心の座標と両目の中点の座標から向きを算出し、基本的に斜め上方向に放つように調整した。
https://github.com/sugyan/eyebeam-herokuapp/blob/8d937600ff1a2798b24daef678b576da3b69690a/app.rb#L135
視線の向きなどは分からないし、顔が上向きなのか下向きなのかすら検出するのは難しい。自動でできるのは限界があると思う。それでも真っ正面向いている画像じゃなければそれなりにイイカンジにビームを放つようになっているとは思う。

キャッシュ

アップロードされた画像、加工された画像はすべてバイナリデータをそのままmemcachedに突っ込んでおり、一切ファイル保存をしていない。一時的なものなのでそのうち消える仕様。残っている間はヒットすればContent-Type: image/jpegでそのデータをそのまま吐き出すことで表示させる。
また顔検出WebAPIからのレスポンスなどもキャッシュして無駄に何度もAPIを消費しないようにはしている。けど色々試してたら結構すぐに回数制限に達してしまったのでもうちょっと調整した方が良いかも…
memcachedを使うRubyクライアントライブラリにはDalliというのが良いらしい、ということで使ってみた。
GitHub - petergoldstein/dalli: High performance memcached client for Ruby

Sinatra + Haml + Bootstrap

Webアプリとしてのバックエンドは、ようやく使い慣れてきたSinatraで。なんだかんだで160行くらいか。まだまだ作法などがちゃんと分かってなくてあんまり自信ない。
HamlTwitter Bootstrapは幾らか使い慣れてきた気がする。

カスタマイズしたい

結局のところ自動でお手軽なのは良いけどあんまり精度よくないし自分でカスタマイズできた方が良いよね、ということで、canvasなどを使ってマウス操作やGUIからビームの発射位置や角度、色、強度、などを調整できた方が嬉しいし楽しいな、と思ってこれからそれを作ろうと思ってcanvasとかを急遽勉強し始めようとしているところ。