クリスマスも近いので福笑いをしようと思った話

はじめに

 この記事はプロコンゼミ(SPC同好会) その1 Advent Calendar 2018 3日目の記事です。

 部内Advent Calendarは去年に引き続いて二回目になります。うちの部員が真面目な記事を書いたり旅行をしたり数日分遅刻をしたりして面白いと思うので、ぜひみてください。
ちなみにその2も存在しており、自分は12/23分を担当しています。そちらは同じく12/23に開催されるCombmofで発表するものと同じ内容にする予定ですが、こちらもよろしくおねがいします。

やったこと

 人物画像を渡すと福笑い(大嘘)ができるアプリケーションを作りました。いえーい

やってる事は下画像を見ればだいたいわかると思います(lena.pngさんごめんなさい…)

f:id:shibh308:20181202230937p:plain


 福笑いは正月に遊ばれる日本の伝統的な遊び(Wikipediaより)です。のっぺらぼうになっている顔の上に顔パーツを載せて、おかしな顔になっているのを見て笑う遊びだそうです。12月は実質1月でお正月みたいなものですしちょうどよいですね。

使ったもの

・Qt(UIをこれで書きます C++をします)
・dlib(機械学習のライブラリです Pythonをつかうことにします 顔認識をするために必要です)
OpenCV(のっぺらぼうにする処理やパーツを取り出す処理など、画像加工に使います これもPython側でおこないます)
・Flask(これなんで必要なんですか?うぇぶ要素を強引にはさむ必要はないとおもいますが…)

実装の流れ

 まずはQtのアプリケーションで画像ファイルをよみこみます。その画像をPOSTしてFlaskに投げ(なんで?)、Python側でよしなに画像を加工して、それをQt側にかえします。(Flaskいる?boost.pythonとかでよくない?)
あとは返ってきた画像をQtで表示して、顔パーツのドラッグと拡大縮小、回転を実装すればおわりです。

 Python側でのdlibを用いた顔認識ですが、調べるといろいろ出てくるのでここでは説明をはぶきます。(正直なところコピペしただけです ごめんなさい)

 その辺に落ちてるやつをコピペしたら顔パーツや輪郭の情報が頂点の配列になって出てきたので、それを使っていろいろやります。
各顔パーツについてですが、頂点情報をもとにfillPolyをしたマスクデータを作って、bitwise_orをした後にresizeするだけです。OpenCV全然わかんなくてもできたので、かなりらくでした。
 顔ののっぺらぼうを作る時はまず輪郭(とか認識できた顔パーツとか全部)の凸包をとります。頂点が順番にならんでなかったりしても凸包すれば優勝!wなので、らくです(OpenCVに関数があるのでやるだけです OpenCVにはなんでもあるなぁ)
その後に輪郭のちょっと内側にある点の色(要するに肌の色)をいくつか抽出します。そして凸包のなかをその色たちで埋めてしまって(ランダムに点をたくさん打つやつをしました)、ぼかし加工とかをした後に元の画像につっこみます。よくわかんない加工をしたらマシな感じになったので、まぁいいんじゃないでしょうか。(?)

 GUIですが、Qtを使うと優勝ができてよいです。画像を読み込んで表示、クリックされた場所のピクセルが透明じゃなかったら(これパーツ数だけ計算されるけどまぁ問題なさそう)ドラッグして画像移動、キー入力で拡大縮小と回転をします。行数が少なくて精神にいいです。

 ネットワーク関連、たいへんです QNetworkRequestとかQNetworkAccessManagerとかQNetworkReplyとか、なにもわからないのでたいへんたいへんでした。
 Flaskも5億年前に3秒触った程度のことしかわからないので、たいへんでした そもそもこれ、なんでlocalhostないでPOSTとかしてるんでしょうか?なんで?boost.pythonでファイル受け渡すかそもそもGUIPythonで書くのが最適っぽい気がします なんでこんな所で消耗してるんですか あほじゃない?

感想

 画像をいろいろ加工するところとかなぜかネットワークの勉強をするところとかソースコードをコピペするするところとか、いろいろ勉強になってよかったです。
 12月に入ってからAdventCalander用のことに手をつけ始めて、結果的に土日を使ってこれを実装することになりました。ぼくにしては働いたほうじゃないでしょうか(?)(ほめて)

 久々に期限ギリギリのデスマーチ気分を味わえて、いい気分転換になりました。ところで今日12/3はテストの最終日です。ぼくはいま12/2の22:30にこの記事を書いていて(追記:いま23じになりました)(追々記:いま記事を書き終わりました 23:55です)、これから記事内容の付け足しとか手抜き部分の一部修正とかきょうのABCの解法確認とかをやってから0:00に記事を投稿する予定なのですが、勉強するじかんはありますか?ありませんね… かなしい
落単で落胆しないようにがんばります。もし落単したら「部活の強制労働のせいで単位が落ちたはなし」を書くよていなので、各位そちらもよろしくおねがいします。

 最後にうちの部員の顔面で福笑いをした画像を載せておわりにしたかったのですが、うちの部員に眼鏡オタクしかいないので福笑いができませんでした…部員各位はもっと福笑いしやすい顔になってほしかったです。
 あとこれたった今気付いたんですけど、これ選択中の顔パーツが隠れるわけでもないし目隠ししてやらないと福笑いにならなくないですか?これ福笑いじゃないじゃん…






おまけのおまけ

 あなたはQt for WebAssembryについて知っていますか?知っているあなたはえらいです 知らなかったあなたも今知ったので偉くなりました 偉いです

細かい説明をするとマサカリが飛んできそうなので省きますが、Qt for WebAssembryを使うと、C++のQtで作ったアプリケーションをそのままブラウザ上で動かす事ができます。(表現のしかたで怒られそうだけどゆるして><)
つまり、これを用いることでぼくが今書いたプログラムをそのままWeb上に公開できる(語弊アリ)わけですね。すごい
実はわざわざC++のQtで書いたり謎の采配をしていたのはこのためで、この機会にWebAssembryを試してみた上でネット上に公開しようと考えていた訳です。


さて、という事で今回のプログラムをブラウザ上で動作させてみましょう。Qtのwikiに詳しい解説が置いてあったり日本語の情報も(少しは)あるので、それを見ながらファイルのダウンロードや操作をしていきます。
最終的にはQtプロジェクトのproファイルをqmakeにかけて、make allでコンパイルする事でhtmlやjsファイルが生成されます。

自分のプロジェクトで正常にqmakeとmakeを終え、htmlファイルが生成されました。では、実行をしてみます。下に結果の画像を添付するので、そちらをご覧ください。






























f:id:shibh308:20181202234502p:plain











おわり