使用TensorFlow.js + WASM + Three.js的浏览器中的视差效果

还记得苹果如何推出具有视差效果的iOS7吗?现在可以直接在浏览器中完成。

视差摄像头threejs



现在,所有笔记本电脑和手机都配有摄像头,因此您可以使用tensoflow模型分析头部和眼睛的位置。另外,SIGGRAPH 2020上的一篇新文章介绍了如何制作便于视差效果的摄影测量数据集。



也许每个人都知道有一个用于神经网络的Tensorflow库,它可以在Python和Javascript语言下运行。神经网络中的卷积过程是一个相当重量级的计算,可以很好地并行化,并且不仅有CPU版本,还有Python的CUDA版本和Javascript的WebGL / WebGPU版本。这很有趣,但是如果您没有NVidia,那么Java上的Tensorflow官方版本可以在PC上更快地运行,因为没有官方支持OpenGL的版本。但是幸运的是,对于所有人而言,TF 2.0具有模块化的体系结构,该体系结构使您可以只考虑本质,而不考虑执行它的语言。还有转换器1.0-> 2.0。







目前,有两种官方的人脸识别模型:facemesh和blazeface。第一个更适合面部表情和面具,第二个更快,并且简单地定义了正方形和特征点,例如眼睛,耳朵,嘴巴。因此,我选择了轻量级版本-blazeface。为什么会有不必要的信息?通常,有可能进一步缩小现有模型,因为除了眼睛的位置之外,我不需要其他任何东西。



目前,浏览器中有5个后端:cpu,wasm,webgl,wasm-simd,webgpu。第一个CPU速度太慢,现在无论如何都不应该使用,后两个CPU太创新了,处于建议阶段,并且处于工作状态,因此最终客户获得零支持。因此,我选择了两个:WebGL和WASM。







从现有基准测试中,您可以看到,对于小型模型,WASM有时比WebGL快。此外,视差可以用于3D场景,并且通过在它们上运行WASM后端,我意识到WASM的性能要好得多,因为离散的笔记本电脑视频卡不能同时输出神经网络和3D场景。为此,我拍摄了一个简单的场景,其中包含 .glb的75个地球仪。该链接是可单击的,并且有WASM。







如果您点击链接,您可能会注意到浏览器要求访问摄像机的权限。问题出现了:如果用户单击否,将会发生什么?在这种情况下,最好不要加载任何东西,然后回退以控制鼠标/陀螺仪,这是明智的。我没有找到tfjs-core和tfjs-converter的ESM版本,所以我没有动态导入,而是使用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(指数移动平均)对它们进行了平滑处理:



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


或以其他方式编写:



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


因此,我们获得了以相机为中心的某个球坐标系中的坐标x,y,z。此外,x和y受相机视角的限制,z是从头部到相机的大概距离。小转弯角度sin(α)α因此x和y可以视为角。



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


摄影测量



出版物SIGGRAPH 2020沉浸式光场视频中带有分层网格表示的日期非常有趣。他们专门制作了照片,以便您可以在一定范围内移动相机,这非常适合视差的想法。视差示例。







3D场景在此处分层创建,并将纹理应用于每个图层。他们用来进行摄影测量的设备看起来同样有趣。他们购买了47台便宜的Yi 4K运动相机,每台价格为10k卢布,然后将它们放置在一个二十面体形状的半球中,三角形网格增加了三倍。之后,每个人都放在三脚架上,并同步照相机进行拍摄。







参考资料






All Articles