MTCNNをPyTorchで試してみる
前回の最後にYOLOとかMTCNNとかも試すって書いたのでやります。YOLOの場合は「物体検出アルゴリズム」なのでネット上で入手できる訓練済みモデルは一般の物体検出を学習させたもので、顔検出にそのままでは転用できないものばかりです。なので今回はネット上で簡単に顔検出の訓練済みモデルが手に入るMTCNNをPyTorchでやってみたいと思います。
MTCNNって?
arXivのリンクはこちら。DeepL*1と共に読んでみます。間違いがあればコメントで教えていただけるとありがたいです。
MTCNNは3つのステージから成り、それぞれが別々のネットワークを持っています。Stage1ではP-Net*2、3層のConvolution層と1回のMaxPooling、1層の全層結合を持ちます。入力画像を複数のサイズにリサイズして(任意の顔の大きさに対応できる)ネットワークに入力し、正確性というよりは高速を目的に顔領域の候補を検出します。
Stage2ではR-Net*3、3層のConvolution層と2回のMaxPooling、2層の全層結合を持ちます。Stage1の出力を基に、顔でない領域候補を消していきます。
Stage3ではO-Net*4、4層のConvolution層と3回のMaxPooling、2層の全層結合を持ちます。Stage2の出力を基に、より正確に顔でない領域候補を消していきます。また、顔のランドマーク(右目、左目、鼻、右口角、左口角の座標)を検出し、最終的な顔の領域を出力します。
また、各StageでNMS(Non-Maximum Suppression)を用いて、大きく重なってる領域候補を削除してます。NMSについてのわかりやすい説明はこちらです。中間層の活性化関数にはPReLU(Parametric Rectified Linear Unit)を使用しています。PReLUとは通常のReLUとは異なり、学習可能なチャネルごとのパラメータを持ち、次の式で表されます。
(あんまり数式の書き方わからん…)
LeakyReLU*5の進化版みたいな感じですかね。
使用したモデル
MTCNNをPyTorchで実装、訓練していた方がGitHubで公開していたので、使わせていただくことに。 github.com 今回も必要な部分だけ写経しました。
検出してみる
前回が悲惨だったためにとても緊張します。前回と同じようにFDDBデータセットから画像をとってきます。結果はこちら。 おお、正確に検出できてる!顔領域は青四角、ランドマークは適当に色分けして丸をつけてます。顔領域はもちろん、ランドマークもほとんどぴったりです。(横向きの写真だと怪しいけど…。)2人いてもどっちもちゃんと検出できてる。
しかし、思ってた以上…。Deepって言ったって全体としてはMaxPooling含めて20層ちょっと、全層結合抜きのVGG16より少し多いくらいです。SSDでは特徴抽出のためだけにVGGを使っていたことを考えれば驚異的…。(まあクラスが顔だけというのもありますが。)
もっと複数人写ってる画像で試してみましょう。ハロプロ公式サイトの各グループのプロフィールページから写真を持ってきます。ランドマークまで描画するとぐちゃぐちゃするので顔領域だけ青四角で描画します。
まずモーニング娘。'20(14人) 1枚目は検出されてない人が何人かいますが、2枚目は1人程度。あと、ほまちゃんが小さめに検出されてる感じです。ランドマークの位置が重視されてるんでしょうか。2枚目のようにごちゃごちゃしててもうまく検出できてます。
次、Juice=Juice(8人) 1枚目は全員検出。2枚目は衣装が白くて背景と同化してるせいで精度が落ちた?
最後に、BEYOOOOONDS(12人) 漏れなく全員検出できてる。すごい。
精度も高く、回転にも比較的寛容なようです。Deep Learning恐るべし、って感じです。ランドマークも検出できるので、GAN用に学習データの顔の位置を調整したりする(FFHQデータセットとかは目の位置が揃ってますね)のにも使えると思います。
次回はOpenCVとdlibあたりと速度とか比較したいと思います。