Effet de parallaxe dans le navigateur avec TensorFlow.js + WASM + Three.js

Rappelez-vous comment Apple a introduit iOS7 avec effet de parallaxe? Maintenant, cela peut être fait directement dans le navigateur.

parallaxe webcam threejs



Tous les ordinateurs portables et téléphones disposent désormais d'un appareil photo, vous pouvez donc analyser la position de la tête et des yeux à l'aide de modèles tensoflow. En outre, un nouvel article de SIGGRAPH 2020 explique comment créer des ensembles de données photogrammétriques pratiques pour l'effet de parallaxe.



Tout le monde sait probablement qu'il existe une bibliothèque Tensorflow pour les réseaux de neurones, elle fonctionne sous les langages Python et Javascript. Le processus de convolution dans les réseaux de neurones est un calcul assez lourd qui est bien parallélisé et il existe des versions non seulement pour le CPU, mais aussi dans CUDA pour Python et WebGL / WebGPU pour Javascript. C'est drôle, mais si vous n'avez pas NVidia, alors la version officielle de Tensorflow en langage Javascript fonctionnera plus rapidement sur le PC, car il n'y a pas de version officielle avec le support OpenGL. Mais heureusement pour tous, TF 2.0 a une architecture modulaire qui vous permet de ne penser qu'à l'essence, et non au langage dans lequel il est exécuté. Il existe également des convertisseurs 1.0 -> 2.0.







Pour le moment, il existe deux modèles officiels de reconnaissance faciale: le facemesh et le blazeface. Le premier est plus adapté aux expressions faciales et aux masques, le second est plus rapide et détermine simplement les points carrés et caractéristiques, tels que les yeux, les oreilles, la bouche. Par conséquent, j'ai pris la version légère - blazeface. Pourquoi des informations inutiles? En général, il peut être possible de réduire encore plus le modèle existant, car à part la position des yeux, je n'ai besoin de rien d'autre.



Il y a actuellement 5 backends dans le navigateur: cpu, wasm, webgl, wasm-simd, webgpu. Le premier processeur est trop lent et ne devrait pas être pris maintenant dans tous les cas, les deux derniers sont trop innovants et sont au stade des propositions et fonctionnent sous les drapeaux, donc il n'y a aucun support pour les clients finaux. Par conséquent, j'ai choisi parmi deux: WebGL et WASM.







À partir des benchmarks existants, vous pouvez voir que pour les petits modèles, WASM est parfois plus rapide que WebGL. De plus, la parallaxe peut être utilisée avec des scènes 3D et en exécutant le backend WASM sur celles-ci, j'ai réalisé que WASM fonctionne beaucoup mieux, car les cartes vidéo discrètes pour ordinateurs portables n'exportent pas simultanément les réseaux neuronaux et les scènes 3D. Pour cela, j'ai pris une scène simple avec 75 globes en .glb. Le lien est cliquable et il y a WASM.







Si vous avez cliqué sur le lien, vous avez probablement remarqué que le navigateur vous a demandé l'autorisation d'accéder au caméscope. La question se pose: que se passera-t-il si l'utilisateur clique sur non? Il serait raisonnable de ne rien charger dans ce cas et de revenir au contrôle souris / gyroscope. Je n'ai pas trouvé la version ESM de tfjs-core et tfjs-converter, donc au lieu de l'importation dynamique, j'ai opté pour une construction plutôt effrayante avec la bibliothèque fetchInject, où l'ordre de chargement des modules compte.



construction fluage
, (Promise.All), , , .

fetchInject([
  'https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface@0.0.5/dist/blazeface.min.js'
], fetchInject([
  'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter@2.0.1/dist/tf-converter.min.js',
  'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@2.0.1/dist/tfjs-backend-wasm.wasm'
], fetchInject([
  'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core@2.0.1/dist/tf-core.min.js'
]))).then(() => {

  tf.wasm.setWasmPath('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@2.0.1/dist/tf-backend-wasm.min.js');

  //some other code

}




Afin de trouver la position de mon regard, je prends la moyenne entre deux yeux. Et il est facile de comprendre que la distance à la tête sera proportionnelle à la distance entre les yeux dans la vidéo, en raison de la similitude des côtés du triangle. Les données de position des yeux provenant du modèle sont assez bruyantes, donc avant de faire les calculs, je les ai lissées en utilisant l'EMA (moyenne mobile exponentielle):



pos = (1 - smooth) * pos + smooth * nextPos;


Ou l'écrire d'une autre manière:



pos *= 1 - smooth;
pos += nextPos * smooth;


Ainsi, nous obtenons les coordonnées x, y, z, dans un certain système de coordonnées sphériques avec le centre de la caméra. De plus, x et y sont limités par l'angle de vue de la caméra, et z est la distance approximative de la tête à celle-ci. Aux petits angles de rotationsjen(α)αdonc x et y peuvent être considérés comme des angles.



pushUpdate({
  x: (eyes[0] + eyes[2]) / video.width - 1,
  y: 1 - (eyes[1] + eyes[3]) / video.width,
  z: defautDist / dist
});


Photogrammétrie



Jeu de dates assez drôle tiré de la publication SIGGRAPH 2020 Vidéo immersive de champ lumineux avec une représentation de maillage en couches. Ils ont fait des images spécifiquement pour que vous puissiez déplacer l'appareil photo dans une certaine plage, ce qui correspond idéalement à l'idée de parallaxe. Exemple de parallaxe.







La scène 3D est créée ici en calques et une texture est appliquée à chaque calque. L'appareil avec lequel ils ont créé la photogrammétrie n'est pas moins drôle. Ils ont acheté 47 caméras d'action bon marché Yi 4K pour 10k roubles chacune, et les ont placées sur l'hémisphère sous la forme d'un icosaèdre dans lequel la grille triangulaire est triplée. Après cela, tout a été placé sur un trépied et les caméras ont été synchronisées pour la prise de vue.







Liens






All Articles