「新春创意」快打开摄像头召唤属于你的虎年吉祥物🐅

实现效果

7.gif

前言

第一篇简单实现了一下支付宝写福字的效果,当时就有一个想法,能不能实现支付宝的扫福呢,查找了许多资料后发现单靠前端还是无法实现,于是我换了个思路,利用 ar 去扫福,召唤虎年吉祥物。本文实现效果也许很 low,但旨在抛砖引玉,希望各路大神能让我大开眼界(春节企划的文章都挺 nb 的……发现大家脑洞和实力简直太强了)

实现的技术路线:AR.js + A-Frame + artoolkit + obj2gltf

关于 AR.js 与 A Frame

首先简单介绍一下 AR.js 和 A-Frame,因为后续看似很少的代码中其实 A-Frame 帮我们做了很多事情,这个后面再说。

AR.js

AR.js 是一个轻量级的增强现实类 JavaScript 库,支持基于标记和位置的增强现实。AR.js 框架包括跨浏览器兼容性,并且支持 WebGL 和 WebRTC,这意味着它可以在 iOS 11 以上的 Android 和 iPhone 设备上正常工作。通过包装许多不同的 AR 框架,包括 three.js,a-frame 和 ARToolKit,AR.js 使得将 AR 引入 Web 应用程序变得更加简单高效。它具有以下优点:

  • 跨浏览器兼容性

  • 即使在较旧的设备上也可以达到 60fps 的高性能

  • 基于 Web,无需安装

  • 开源,可免费访问

  • 使用 WebGL 和 WebRTC 在所有移动设备上均可使用

  • 无需额外或不常见的硬件

  • 可以用不到 10 行 HTML 来完成

A-Frame

A-Frame 是一个用来构建虚拟现实(VR)应用的网页开发框架。由 WebVR 的发起人 Mozilla VR 团队所开发,是当下用来开发 WebVR 内容主流技术方案。WebVR 是一个完全开源的项目,已成长为领先的 VR 社区。

A-Frame 基于 HTML,容易上手。但是 A-Frame 不仅仅是一个 3D 场景渲染引擎或者一个标记语言。其核心思想是基于 Three.js 来提供一个声明式、可扩展以及组件化的编程结构。

A-Frame 让我们能够在纯 html 中使用组件式的标签来快速开发,下边贴上基本代码,用 vue 的兄弟会觉得很舒服:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<html>

<head>

    <script src="https://aframe.io/releases/1.1.0/aframe.min.js"></script>

</head>

<body>

<a-scene>

<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>

<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>

<a-cylinder

position="1 0.75 -3"

radius="0.5"

height="1.5"

color="#FFC65D"

></a-cylinder>

<a-plane

position="0 0 -4"

rotation="-90 0 0"

width="4"

height="4"

color="#7BC8A4"

></a-plane>

<a-sky color="#ECECEC"></a-sky>

</a-scene>

</body>

</html>

总结一下 A-Frame 的特性:

  • 简化 VR 制作: 只需要引入 <script> 标签 和 <a-scene>,A-Frame 将自动生成 3D 渲染的样板代码,VR 相关设置和缺省的交互控制。不需要安装任何东西也无需编译构建。

  • 声明式 HTML: HTML 很容易阅读,理解和复制粘贴。

  • 实体-组件架构: A-Frame 基于强大的 three.js 框架, 同时提供声明式、组件化、可复用的实体组件结构。HTML 只是冰山的一角,开发者可以自由的使用 JavaScript、DOM API,Three.js,WebVR,和 WebGL。

  • 高性能: A-Frame 从底层对 WebVR 做了优化,尽管 A-Frame 使用 DOM,但其元素并不接触浏览器的布局引擎。3D 对象的更新全部在低开销内存中通过单个 requestAnimationFrame 来调用,甚至能够像本地应用一样来运行 (90+ FPS)。

  • 工具无关性: 由于是构建在 HTML 之上,所以 A-Frame 和大多数开发库、框架和工具如 React, Vue.js, Angular, d3.js, Ember.js, jQuery 兼容。

实现

前置资源准备

首先准备好aframe及其继承了 ar 和 nft 的 js 文件(可以从我的项目中取),一个用来扫的图片(图片的要素尽量多,jpg 格式,长宽一致)以及一个识别后召唤的吉祥物模型(obj 格式或 gltf 格式)。

标志图片

首先我们需要对图片处理一下,因为我们识别的是自然图片所以需要利用artoolkit(项目代码中有安装包)对图片进行特征点提取,特征点越多识别的越准确,这也是为什么我提醒要选择要素多的图片。

artoolkit 安装后的文件目录为C:\Program Files (x86)\ARToolKit5,我们进入bin目录,添加一个image文件夹,将我们选择的图片放进去,接着在bin目录下打开终端,输入命令:

1
2
$ genTexData.exe 图片相对路径

image.png

接着回车两次,这两步是选择提取图片特征的程度,数值越大提取的特征越多。当相机离图片越近的时候,追踪效果会越好。此处使用默认值。

接下来需要选择最大最小分辨率,根据不同相机分辨率及相机远近有不同取值,一般使用20到120最为合适。而我们这边最大分辨率只有96,所以我选择20到96。

image.png

接着回车,等待生成特征点,图片目录下会生成.fset,.fset3,.iset三个文件,这些文件就是我们需要的。

我们使用 dispFeatureSet 工具可以显示一下看看特征点提取情况:

image.png

吉祥物模型

模型就在网上找免费的模型就好,如果模型是 glTF 格式是最完美的,其他格式需要转换成模型的通用 obj 格式,然后利用 obj2gltf 工具(代码仓库中提供)将其转换成 gltf 模式。

1
node bin/obj2gltf.js -i obj模型路径 -o 输出路径/输出模型名.gltf

代码

首先我们利用 a-scene 搭建出一个场景,开启arjsgesture-detector手势检测,vr-mode-ui="enabled: false;"不展示 vr 按钮,并放置一个相机组件用来调用我们的设备摄像头。

1
2
3
4
5
<a-scene arjs vr-mode-ui="enabled: false;" gesture-detector>

<a-entity camera></a-entity>

</a-scene>

接下来将我们生成的模型、图片及其特征文件放到项目目录中,并使用 nft 组件并进行相应配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<a-nft

type="nft"

url="./assets/2"

>

<a-entity gltf-model="./assets/tiger.gltf" scale="1 1 1" position="0 0 0">

</a-entity>

</a-nft>

注意nft的url中写的是图片的名,不需要后缀,在它里面添加我们识别后想要展示的模型,并设置放大级别和位置。

问题

到这里其实这个代码就完成了,我们兴致勃勃的对项目开启live-server,用手机访问一下页面。

咦,为什么提示我们的浏览器没有navigator.mediaDevices,百度了一下发现,浏览器端想要调用摄像头只有几种情况:

  • file

  • localhost

  • https

那我们如果在本地该怎么调试呢,这里介绍一个一直在用的内网穿透神器:ngrok(安装包也放在仓库中了)

解压打开后执行ngrok http 8080,第一次需要注册账号并绑定Authtoken,绑定完成后重启ngrok再执行。成功后会返回给你三个地址,本地、http和https的url路径,我们使用https的即可。

image.png

手机访问地址后就可以开启摄像头权限了。

因为是内网穿透,所以打开页面及识别加载都会比较慢。

最后

关于识别的图片,我作为一个前端认为如果想识别通用的福字应该是需要进行模型训练的,但是我不会,所以就改成了识别自然图片,期待大佬们的完善。


「新春创意」快打开摄像头召唤属于你的虎年吉祥物🐅
https://moewang0321.github.io/2022/01/16/「新春创意」快打开摄像头召唤属于你的虎年吉祥物🐅/
作者
Moe Wang
发布于
2022年1月16日
许可协议