LoginSignup
14
12

More than 3 years have passed since last update.

TensorFlow.jsのfacemeshで顔向き推定を試してみた その2

Last updated at Posted at 2020-05-26

これはTensorFlow.jsのfacemeshで3D座標から顔向き推定の実証実験。

前回はOpenCVのSolvePnPとRodriguesで回転行列(rotation matrix)を求めました。
今回はアプローチを変えてfacemeshの3D座標から直接回転行列を求めます。

元ネタはこちらコード

回転行列の求め方(コード紹介)

行列演算はTensorFlow.jsを利用しました。
TensorFlow.jsでは演算子をサポートしていないのでとても見辛いです。
TensorFlow.js API
使ったメモリはdisposeやTidyで解放が必要です

参考までに

  • div .. 割り算
  • sub .. 引き算
  • mul .. 掛け算

コードでは、顔の適当な3D座標(元コードでは全ての座標、今回は適当に選択した座標:輪郭のみ)と輪郭の端の4点と目の位置の引数からスケールを取得し、中心を求めています。


let fecePoints = tf.tensor(faces);
let eye1 = tf.tensor1d(rightEye);
let eye2 = tf.tensor1d(leftEye);

let scales = fecePoints.div(tf.norm(eye1.sub(eye2))).mul(0.06);
let centered = scales.sub(scales.mean(axis=0));

let c00 = centered.slice(0,1).as1D();
let c09 = centered.slice(9,1).as1D();
let c18 = centered.slice(18,1).as1D();
let c27 = centered.slice(27,1).as1D();

3x3のrotation matrixを求めます。


let rotate0 = c18.sub(c00).div(tf.norm(c18.sub(c00)));
let rotate1 = c09.sub(c27).div(tf.norm(c09.sub(c27)));
let rotate = tf.concat([rotate0, rotate1]).arraySync();

let m00 = rotate[0];
let m01 = rotate[1];
let m02 = rotate[2];

let m10 = rotate[3];
let m11 = rotate[4];
let m12 = rotate[5];

// cross product
let m20 = m01*m12 - m02*m11;
let m21 = m02*m10 - m00*m12;
let m22 = m00*m11 - m01*m10;

rotation matrixが解れば、Rotation Matrix to Euler Anglesで変換します。

製作物

オンラインデモ

おわりに

facemeshの三次元座標で顔の向きを推定しました。
AIで三次元座標が解ることで、簡単に顔の向きが推定出来るようになり、よく使われるSolvePnPの手法が必須ではなくなりました。
これまで当然として使われていた処理が使われなくなるのは感慨深いものがあります。
今後も、定期的に自身の情報をアップデートしていければと思います。

14
12
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12