Русский
Русский
English
Статистика
Реклама

Эффект параллакса в браузере с помощью TensorFlow.js WASM Three.js

Помните как Apple представила iOS7 c эффектом параллакса? Сегодня я обьясню как я сделал это прямо в браузере.
image

На всех ноутбуках и телефонах сейчас есть камера, поэтому можно с помощью tensoflow моделей анализировать положения головы и глаз.



Наверно всем известно что есть библиотека Tensorflow для нейронных сетей, она работает под языком Python и Javascript. Процесс свертки в нейронных сетях это достаточно тяжеловесное вычисление, которое хорошо параллелится и существуют версии не только для CPU, но и на CUDA под Python и WebGL/WebGPU под Javascript. Забавно, но если у вас не NVidia, то оффициальная сборка Tensorflow на языке Javascript будет на ПК будет работать быстрее, так как нет официальной сборки с поддержкой OpenGL. Но к счастью для всех TF 2.0 имеет модульную архитектуру, которая позволяет думать только о самой сути, а не языке, на котором это выполняется. Так же существуют конвертеры 1.0 -> 2.0, которые я пока сам особо не пробовал.



На данный момент есть две официальные модели для распознования лица: facemesh и blazeface. Первая больше подходит для мимики и масок, вторая шустрее и просто определяет квадрат и характерные точки, такие как глаза, уши, рот. Поэтому я взял легковесный вариант blazeface. Зачем лишняя информация? Вообще может быть можно существующую модель еще уменьшить, так как кроме положения глаз, мне больше ничего не нужно.

В браузере на данный момент существует 5 бэкендов: cpu, wasm, webgl, wasm-simd, webgpu. Первый СPU слишком медленный и его сейчас не стоит брать ни в каких случаях, последний два слишком инновационны и находятся на стадии пропосалов и работают под флагами, так что поддержка у конечных клиентов нулевая. Поэтому я выбирал из двух: WebGL и WASM.



По существующим бенчмаркам можно увидеть, что что для маленьких моделей WASM работает порой быстрее чем WebGL. Кроме этого, параллакс может использоваться с 3д сценами и запуская WASM бэкенд на них, я понял что WASM работает гораздо лучше, так как дискретные видеокарты ноутбуков, не вывозят одновременно нейросети и 3д сцены. Для этого я взял простую сцену с 75-ю гловами в .glb. Ссылка кликабельная и там WASM.



Если вы перешли по ссылке, вы наверно заметили, что браузер спросил разрешение на доступ к видеокамере. Возникает вопрос: что будет, если пользователь нажал нет? Разумно было бы ничего не грузить в таком случае и фоллбэчить на управление мышью\гироскопом. Я не нашел ESM версию tfjs-core и tfjs-converter, так что вместо динамического импорта, я остановился на довольно криповой конструкции с бибилиотекой fetchInject, где порядок загрузки модулей имеет значение.
криповая конструкция
Забавно то, что порядок расположения имеет значение и нельзя их оборачивать в один массив (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}



Для того что бы найти положение взгляда, я беру среднее между двумя глазами. И легко понять что растояние до головы, будет пропорционально растоянию между глазами на видео, в силу подобия сторон треугольника. Данные о положении глаз, которые приходят из модели довольно зашумленные, поэтому прежде чем производить рачеты, я их сгладил с помощью скользящей средней EMA (Exponential Moving Average)

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

Или записав по другому

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


Таким образом мы получаем координаты x, y, z, в некой сферической системе координат с центром в камере. Причем x и y ограничены углом обзора камеры, а z это примерное растояние от головы до нее. На малых углах поворота $sin(\alpha) \approx \alpha$, так что x и y можно считать за углы.

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


Фотограмметрия



Довольно забавный дата сет с публикации SIGGRAPH 2020 Immersive light field video with a layered mesh representation. Они делали картинки специально для того что бы можно было двигать камеру в некотором диапазоне, что идеально ложится под идею параллакса. Пример с параллаксом.



3д сцена тут создается послойно, и на каждый слой наложена текстура. Не менее забавно выглядит дейвайс, с помощью которого они создавали фотограмметрию. Они купили 47 дешевых экш камер Yi 4K за 10к рублей каждая, и разместили их на полусферу в форме икосаэдра в котором треугольная сетка утроена. После этого все разместили на штатив и камеры синхронизировали для сьемки.



Ссылки:


Источник: habr.com
К списку статей
Опубликовано: 29.06.2020 08:16:31
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Javascript

Tensorflow

Webassembly

Webgl

3d

Tfjs

Wasm

Three.js

Категории

Последние комментарии

© 2006-2020, personeltest.ru