UnityARKitPluginを使ったAR顔変形

# はじめに

こんにちわ。[北千住デザイン](http://kitasenjudesign.com/)の渡邊です。

21_21 DESIGN SIGHTで行われている[「AUDIO ARCHITECTURE展」](http://www.2121designsight.jp/program/audio_architecture/)のために[JIDO-RHYTHM](http://kitasenjudesign.com/jido-rhythm/)という自撮りするとMusicVideoができるアプリを制作しました。[Unity-ARKit-Plugin](https://bitbucket.org/Unity-Technologies/unity-arkit-plugin)を使って制作しています。ここではその中で使われている、顔の変形のやり方について解説します。

スマートじゃない部分もあると思いますが、サンプルコードはこちらにあげました:bow_tone1:
https://github.com/kitasenjudesign/UnityARFaceDeformation

# つくったアプリ
コーネリアスの曲に合わせて、４5種類ほどのエフェクトが切り替わっていきます。音に合わせて、顔を歪めるエフェクトを多用しています。iPhoneX用のアプリです。

![_all_2b.gif](https://qiita-image-store.s3.amazonaws.com/0/17747/ca9067d9-8c30-faa1-1417-1805da254a95.gif)


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Selfie Music Video App “JIDO-RHYTHM” <br>をリリースしました!! ぜひ録画してシェアしてください!!<a href="https://t.co/8W8XdT3Y29">https://t.co/8W8XdT3Y29</a> <a href="https://twitter.com/hashtag/AudioArchitecture?src=hash&amp;ref_src=twsrc%5Etfw">#AudioArchitecture</a> <a href="https://twitter.com/hashtag/Cornelius?src=hash&amp;ref_src=twsrc%5Etfw">#Cornelius</a> <a href="https://twitter.com/hashtag/iPhoneX?src=hash&amp;ref_src=twsrc%5Etfw">#iPhoneX</a> <a href="https://twitter.com/hashtag/arkit?src=hash&amp;ref_src=twsrc%5Etfw">#arkit</a> <a href="https://twitter.com/hashtag/madewithunity?src=hash&amp;ref_src=twsrc%5Etfw">#madewithunity</a> <a href="https://t.co/IbT7oiQzHq">pic.twitter.com/IbT7oiQzHq</a></p>&mdash; KitasenjuDesign (@kitasenjudesign) <a href="https://twitter.com/kitasenjudesign/status/1012971020116881408?ref_src=twsrc%5Etfw">2018年6月30日</a></blockquote>


# 使用している技術
UnityからARkitを扱うことができる[Unity-ARKit-Plugin](https://bitbucket.org/Unity-Technologies/unity-arkit-plugin)を使っています。その中に[FaceTrackingの機能](https://blogs.unity3d.com/jp/2017/11/03/arkit-face-tracking-on-iphone-x/)もあります。TrueDepthカメラを使っているため、現状使えるのはiPhoneXだけですが、顔を3D的にトラッキングすることが可能になっています。

# 顔変形について
FaceTrackingというと、トラッキングされたデータを元にして、別のもの（Animojiとか）を動かすということが多いかもしれません。しかし、このアプリでは自分の顔をそのまま変形させる、ということをやってました。

## やりかた
カメラからの画像に対し、顔部分にトラッキングされたMeshを配置する、というサンプル（FaceMeshScene）が既に用意されているので、これを元に作ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17747/c0743f0e-ac96-0af6-ed8f-4df9bca52d6e.png)

このMeshに、カメラからの画像をそのままテクスチャとして貼り付け、Meshの頂点を動かすことで、あたかも自分の顔が歪んでいるように見せます。

### 01 YCbCrをRGBに
カメラからの入力がYCbCrなので、簡単化のためRGBにし、一度レンダーテクスチャに保存します。シェーダーはサンプルに入ってたものを[少し改造](https://github.com/kitasenjudesign/UnityARFaceDeformation/blob/master/Assets/FaceDeformation/Shaders/YCbCrToRGB.shader)。

### 02 Meshの目と口をふさぐ
FaceTrackingのサンプルを見るとわかりますが、顔がトラッキングされるたびに、Meshの情報がやってきます。ただ、そのメッシュは上記のキャプチャのように目と口に穴が空いています。今回はそれが都合が悪かったので、この目と口の穴を塞ぐために、頂点インデックスを追加しました。新たに作った頂点インデックスは[こちら](https://github.com/kitasenjudesign/UnityARFaceDeformation/blob/master/Assets/FaceDeformation/Scripts/FaceIndices.cs)。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17747/a4409621-4f06-e23b-d643-5568a61e354e.png)

やり方としては一度、顔のMeshをobjデータで書き出して、Cinema4Dで読み込んだのち、目と口を塞ぎ、塞いで増えた分の頂点インデックスを取得する、というような手順でやりました:weary:

注: ネイティブだと口をふさぐパラメータがあるらしい。。。

### 03 シェーダー

カメラ画像をそのままテクスチャにし、メッシュの頂点座標をスクリーン座標に変換しそれをUVとして使えば良いと考えました。ただ、このメッシュを正しい顔の位置に限らず移動や回転などもしたかったので、UVの計算にModelMatrixをそのまま使うとテクスチャの位置もずれてしまいます。なので、引数でModelMatrixを渡しています。[こんな感じ](https://github.com/kitasenjudesign/UnityARFaceDeformation/blob/master/Assets/FaceDeformation/Shaders/FaceDeformation.shader)になりました。


# 変形サンプル
変形サンプルをいくつか作りました。頂点シェーダーを使って変形させています。立体的な変形が可能です。

## 01 小さい顔
![01.gif](https://qiita-image-store.s3.amazonaws.com/0/17747/044739e6-bc28-18af-ccb8-7e532b183f95.gif)
頭の辺に縮小して顔を置いているだけ。

## 02 ノイズで歪む
![02.gif](https://qiita-image-store.s3.amazonaws.com/0/17747/75b79e14-b8cc-7012-18b9-05ba8bc9c5c5.gif)
Z方向に押し出しつつ、ノイズで歪めている。
顔のつなぎ目が破綻しないようにDisplacementMap的な画像で変形範囲を制限している。

## 03 諭吉
![04.gif](https://qiita-image-store.s3.amazonaws.com/0/17747/8368c20f-27ef-35b7-d17b-201aca4c0001.gif)
同じくDisplacementMap的な画像で目と口を動かしている。

## 04 トゲトゲ
![03.gif](https://qiita-image-store.s3.amazonaws.com/0/17747/54312664-9cf1-3282-3c8e-323ba8da95c1.gif)

[同じくDisplacementMap的な画像](https://github.com/kitasenjudesign/UnityARFaceDeformation/blob/master/Assets/FaceDeformation/Materials/Textures/FaceSharp.png)を作ってとんがらせた。
球面座標にして頂点を放射状に伸びるようにしている。


# 困ってるところ
FaceTrackingを使っていると、[たまにフリーズしてしまう現象](https://bitbucket.org/Unity-Technologies/unity-arkit-plugin/issues/4/facetracking-app-freeze)があります。
解決方法がわかったらどなたか教えてください。。

# おわりに
以上、AR顔変形についてでした。このFaceTrackingは、まだ色々使えそうです。
あと、会社をやめ、フリーランスになったので、お仕事募集中です:pray_tone2: