Demoについて
このjeelizWebojiというレポジトリーにある、racoonというdemo(Cameraへのアクセス許可が表情認識のために要求されます)で、source codeはこちらです。
まずは、ライブdemoをここで試して頂きたいのですが、このdemoではこの表情認識API(難読化されていますがドキュメントがあります。)と3つのhelperが使われています。
そこでまずこの3つのhelperと、それらのhelperのまとめ役であるdemo_webojiThreejs.jsというファイルについて、それぞれ簡単にですが説明します。
- demo_webojiThreejs.jsは2で言及するhelperが作ったinitという関数にThree.jsの描画に必要なcanvasのIDや、3Dモデル素材へのパス、ニューラルネットワークの重みデータへのパスなどを渡して実行しているだけです。
JavaScript
1// 大雑把な構造 [demo_webojiThreejs.js] 2THREE.JeelizHelper.init(/*様々なパラメータ*/);
- 一つ目のhelperであるThreeJeelizHelper.jsは、ほかの二つのhelperなどを使いながら、その内で多くの関数を定義したあと、最終的にinitを含むいくつかの関数をひとつのobjectにまとめてTHREEにJeelizHelperという名で代入しています。
JavaScript
1// 大雑把な構造 [ThreeJeelizHelper.js] 2THREE.JeelizHelper = (function () { 3 const that = {/*initを含むいくつかの関数*/}; 4 return that; 5})();
- 二つ目のThreeMorphAnimGeomBuilder.jsと、三つ目のThreeMorphFlexibleMaterialBuilder.jsというhelperはそれぞれ、3Dモデルのgeometryとmaterialの作成を担当する関数です。
ここでさらに付け足してしておきますと、このdemoにおけるThree.jsのgeometryとmaterialは少し特殊なアニメーション技法であるMorph Target(このStackOverflowの回答で簡単に説明されています。)を使用するため、あまり見ないメソッドが使われているようです。
私の理解では、Morph Targetとは人間の顔のアニメーションなどに用いられる手法で、例えば[笑顔, 驚き顔, 怒り顔]といった3つの表情のgeometry(これらをmorph targetという)をあらかじめ用意しておいて、アニメーションの過程でmorph coefficientsまたはmorph target influenceと呼ばれる各表情の強さを表す配列([0.1, 0.3, 0.6]などで、各要素が、同じindexのgeometryの最終的に描画されるmeshへの影響力を表す。)の値を変化させることで、笑顔と驚きの中間の表情(morphTargetInfluences = [0.5, 0.5, 0.0]などになる)などを計算することが可能になるようです。
前置きが長くなりましたが質問について
プログラムの大雑把な動きとしては、
Cameraからのvideo stream
->
APIで表情認識し顔のrotationやmorph target influencesを計算
->
Three.jsのanimation内でAPIから値を取得して利用
というものになります。
ただ、このanimationが少し複雑で、rotationなどのシンプルな変化はJavaScriptで行い、morph targetに関する重い処理はThreeMorphFlexibleMaterialBuilder.js内で作ったGLSL codeを用いてGPUで行っているようなのです。
このGLSLによるmorph targetはAPIからリアルタイムでmorph target influenceの計算結果を取得する必要があると思うのですが、このJavaScriptで書かれたAPIとGLSLがどうリアルタイムで繋がっているのかがわかりません。
それらしき部分はThreeJeelizHelper.js内で一か所、ThreeMorphAnimGeomBuilder()のsuccessCallbackの中で
JavaScript
1const morphTargetInfluencesDst = JEEFACETRANSFERAPI.get_morphTargetInfluencesStabilized();
という箇所があるのですが、この部分はconsoleで確認してみても一度しか実行されていませんし、リアルタイムで何度も呼び出されているようには見えません。
いったいGLSLはどうやってAPIの計算結果を取得しているのでしょうか?
長くなりましたので、わかりにくいところがありましたら遠慮なく質問いただければ、できる範囲で回答させて頂きます。
この分野では新参者なので勘違いなどあるかと思いますが、ご指摘いただければ大変ありがたく思います。
宜しくお願いいたします。
あなたの回答
tips
プレビュー