いしぐめも

プログラミングとかしたことを書きます。

プロフィールムービー用に顔の正規化を行うスクリプトを書きました

PythonOpenCVを使って、顔写真の目と口の位置を合わせる処理「正規化」のスクリプトを組んでみました。

顔写真は撮った時のタイミングによって角度だったり、人物だったりが異なるわけですが、それを両目の位置、口の両端を手動で選択することで一定の位置にそろえることができるというものです。

はじめに

私事ですが、最近結婚式を挙げました。披露宴ではド定番の演出として新郎新婦が中座するときにお客さんに見てもらう「プロフィールムービー」というものがありますが、画像処理を齧った身としては凝った演出をしてみたくなるものです。というわけで今回は顔の正規化にチャレンジしてみました。

正規化とは

機械学習でGANとかを勉強し始めて「正規化」というものがあることを知りました。所定の位置に両目と口の位置を揃える処理ですが、どの正規化を適用するかなどは論文によって異なるのかもしれません。

以下に、いわゆる PGGAN の論文「Progressive Growing of GANs for Improved Quality, Stability, and Variation1」から正規化部分の画像を引用します。

f:id:yoh1496:20211103000018p:plain
ICLR 2018 PGGAN Figure 8 より引用

おそらく学習をさせる際に少しでもパラメータを減らす効果があるんじゃないかなと思います。が、それはある意味、そこに目がある口があるという前提になるので下記みたいに顔でないものに適用すると顔が出てくることになります。シャポコさんのツイートが例として面白かったので引用させていただきます(問題あれば言ってください)

正規化の手順

PGGANで使用している正規化手順は以下の通り。

  1. 左目から右目を結ぶベクトル x'
  2. 両目の中点から口の中点を結ぶベクトル y'
  3. 両目の中点から口の中点に向けて 0.1 |y'| を進めた位置を中点 c
  4. 切り出す幅・高さは 4.0 * 両目間の距離, 3.6 * 口と目の間の距離 のどちらかを使用する
  5. x' と平行な単位ベクトルと、それに垂直な単位ベクトルを新たなx軸, y軸とする

こんな感じでしょうか。これをスクリプトに起こしました。

正規化スクリプトの使い方

上記の正規化をポチポチGUIで実行できるスクリプトにしました。プルリク大歓迎です。

github.com

input画像の準備

index.py と同じ階層に input というフォルダを作り、画像ファイルを放り込んでください。サブフォルダがあっても大丈夫です。

f:id:yoh1496:20211103011844p:plain
インプット例(画像はpixabayから)

以下に使用した素材へのリンクを貼っておきます。

スクリプト実行

実行するにはリポジトリ内の index.py を実行してください。

python index.py

f:id:yoh1496:20211103012658p:plain
WinPythonでもopencvを導入すれば実行できます

点選択

まずはインプット画像が表示されます。

f:id:yoh1496:20211103013040p:plain
インプット画像が表示される

画像上の目と口の位置をクリックして決めていきます。順序は「画像向かって左の目 → 画像向かって右の目 → 口の左端 → 口の右端」です。

ただし、このときフィードバックないので注意してください。選び終わった点ぐらい表示すればよかったかな…(プルリク大歓迎です)

f:id:yoh1496:20211103013219p:plain
正規化後

4点決めた時点で正規化された画像が表示されます。問題なければエンターキーを押して次にすすんでください。

画像が一巡するまでこれを繰り返したら終了です。なおアンドゥなどという高度な機能は実装していないのでミスったら最初からやり直してください。(プルリク大歓迎です)

結果

結果は output フォルダに作成されます。

f:id:yoh1496:20211103013617p:plain
結果

こんな感じに、すべての顔が画像中心に来ていれば成功です。

出力時の画像サイズ、入力時の表示サイズはパラメータで変更できるようにしてあるので、適宜いじって使用してください。(拡大縮小機能????プルリク大歓迎です)

これが正規化パワーだ!

f:id:yoh1496:20211103014058g:plain
正規化結果アニメーション

というわけで、こんな感じにいろんな角度・向きで取られた顔写真を正規化することで、たとえそれが別人であっても顔が重なるように処理することができました。

このツールを作ったわけ

こんな正規化ツールを作って何がしたかったかのかは、冒頭にも記載した通りプロフィールムービーの作成です。

実家にあった子供の頃の写真と今までの写真を全部正規化して時系列に並べることで成長の過程をアニメーションで見せたく、また、子供の頃の写真ってほかの友達と映っていたり真正面を向いていなかったりで顔の識別だったり顔のランドマーク検出がうまくいかないだろうなーということが予見されたので、甘んじて手動でポチポチやるツールになりました。

結果、数百枚あった自分の写真をポチポチ正規化すると、「(昔はかわいかったのに)どうしてこうなった!」というおぞましいアニメーションができあがりました。

尺の関係と、おそらく当日プロジェクターで投影してもよくわからないだろうなという懸念から使用は見送りましたが、自分のプロフィールムービーで使ってやるぜ!という方がいらしたら是非使ってやってください。

終わりに

以上、顔の正規化スクリプトの話でした。

OpenCVのマウスコールバックなんて18095710978万年ぶりに使ったので色々と懐かしく、楽しいプログラミングでした。


  1. Tero Karras, Timo Aila, Samuli Laine, Jaakko Lehtinen: “Progressive Growing of GANs for Improved Quality, Stability, and Variation”, 2017; arXiv:1710.10196.