blog icon indicating copy to clipboard operation
blog copied to clipboard

实现一个简单但有趣的AR效果(Web)

Open JChehe opened this issue 7 years ago • 0 comments

本文涉及多个 Codepen 案例,若想获得更佳体验,请到 凹凸实验室博客 阅读,谢谢。

封面

增强现实(Augmented Reality,简称AR):是一种实时地计算摄影机影像的位置及角度并加上相应图像、视频、3D模型的技术,这种技术的目标是在屏幕上把虚拟世界套在现实世界并进行互动。

本文将让你了解“如何通过 Web 技术实现一个简单但有趣的 AR 效果”。

实现分析

正如文章开头说道:AR 是将真实环境与虚拟物体实时地叠加到一个画面。因此我们需要通过摄像头实时获取真实环境,并通过识别算法识别与分析真实环境中特定的物体,然后结合得到的数据,将虚拟物体以某种方式结合到画面中。

结合我们的案例,可得出以下步骤:

  1. 获取视频源
  2. 分析源,并识别出 Marker 位置
  3. 将虚拟物体叠加在 Marker 上
  4. 将最终画面显示在屏幕上

下面我们就根据以上步骤逐点分析。

技术分析

获取视频源

不依赖 FlashSilverlight,我们使用 navigator.getUserMedia() API,该 API 允许 web 应用获取用户的摄像头与麦克风流(stream)。

<!-- 若不加 autoplay,则会停留在第一帧 -->
<video autoplay></video>


navigator.getUserMedia  = navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia;

var video = document.querySelector('video');
var constraints = {
  video: true
}

function successCallback(stream) {
  // 此处利用该 window.URL 对象的 createObjectURL 方法将 blob 转为 url。
  if (window.URL) {
    video.src = window.URL.createObjectURL(stream); // 用来创建 video 可以播放的 src
  } else {
    video.src = stream;
  }
}

function errorCallback(error) {
  console.log('navigator.getUserMedia error: ', error);
}

if (navigator.getUserMedia) {
  navigator.getUserMedia({video: true}, successCallback, errorCallback);
} else {
  console.log('getUserMedia() is not supported in your browser')
  video.src = 'somevideo.webm'; // fallback.
}

上述 API 已不被推荐,建议使用新标准 API:navigator.mediaDevices.getUserMedia()

navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
  /* use the stream */
}).catch(function(err) {
  /* handle the error */
});

另外,可通过 constraints 参数设置以下选项:

  • 启用 video、audio 二者其一或两者同时启用
  • 匹配摄像头分辨率(若设备拥有不止一个摄像头)
  • 选择前后摄像头
navigator.getUserMedia() 兼容性问题

目前 IOS 设备的微信和 Safari 均不支持,较新的安卓和桌面端浏览器均支持。

另外,出于安全问题考虑,Chrome 只支持 HTTPS 页面启用摄像头。因此,我们可以用 Firefox,或者借助一些线上编辑器,如 jsbinjsFiddle 等进行开发测试。


识别

得到视频源后,我们需要对图像中的物体(本案例是 Marker)进行实时识别。下面提供两个可实现识别的库:

正如其名,它们是 aruco 和 artoolkit 的 JavaScript 版本。本文仅对第一个库进行介绍。

ArUco 是一个基于 OpenCV 的 AR 轻量库。

OpenCV(Open Source Computer Vision Library):是一个跨平台的计算机视觉库。它可用于开发实时的图像处理、计算机视觉以及模式识别程序。

jsaruco 能识别视频每帧画面中的 Marker 位置(含 4 个角坐标)。获取坐标后,我们就能将虚拟物体放在真实环境的适当位置了。关于 jsaruco 的介绍和用法,可到 这里 查看。

结合真实环境和虚拟物体

对图像的处理,Canvas(WebGL) 无疑是目前 Web 的最佳选择。

虚拟对象若是 2D 的,则直接利用 Canvas 2D API 在相应坐标上进行绘制。若虚拟对象是 3D 的,则可使用 Three.jsA-Frame 等 3D 库(当然,你也可以直接用 WebGL)。

如果你对 Three.js 还不了解,可以看看 《Three.js入门指南》

另外,使用 A-Frame 可让你更快和更轻易地体验到 3D 的乐趣,仅需 10 行代码即可实现 AR,具体可阅读这篇文章 《Augmented Reality in 10 Lines of HTML》

Marker 分析

每个识别库都有其自身的实现方式。因此,一些 Marker 可能只适用于某个库。对于 jsaruco,它对 Marker 的要求如下:

一个 7x7 的正方形,其外层是“不用”的黑边。内部 5x5 单元格则组成了 ID 信息。其中,每行需要遵循以下模式:

white - black - black - black - black
white - black - white - white - white
black - white - black - black - white
black - white - white - white - black

因此,根据上述信息,我们可以得出该库最多可识别 1024(4的5次方) 个 Marker。也就是说:每个 Marker 对应唯一一个 ID,然后我们可以利用 ID 指定显示的虚拟对象。

一个合格的 Marker 应该是这样子:
Marker 分析

可通过这个 链接,获取 jsaruco 的更多 Marker。

当然,更先进的图像识别库不仅能识别 Marker,也可以识别你指定的图片,甚至是自然特征跟踪( Natural Feature Tracking)和 SLAM(Simultaneous Localization and Mapping,即时定位与地图构建)。

Natural Feature
自然特征跟踪

SLAM
SLAM

实现案例

建议使用带有摄像头的电脑体验以下案例(注意不要被自己的头像惊艳到~)。

另外,由于以下案例均未要求特定 ID 的 Marker,因此你可以选择以下 Marker(拍照或打印),或者在 这里 挑选一个进行体验。

此处输入图片的描述  
Marker

想体验以下案例,需要先对某一个 Marker 拍下或打印,然后将其展示在摄像头前。

另外,为了保持文章的简洁,在此就不直接展示以下案例的实现代码。若需要,则直接查看案例源码。

再次提醒:以下案例均在电脑上进行开发测试,未针对移动端设备进行优化测试。

除了第一个案例,其余均以动画的方式展示虚拟元素。

显示 2D 图

当你展示团队 Logo 时,链接>>。  
凹凸实验室Logo

显示心跳

当你看到“男神/女神”时,链接>>。  
心跳

显示卡片

当需要展示某个人的身份信息时,链接>>。  
卡片

显示 3D 地球

当展示我们的地球母亲时,链接>>。  
3D 地球

显示 3D 商品

当展示我们的商品时,链接>>。  
3D 商品——茶壶

最后

由于笔者才疏学浅,实现的案例未必完全符合 AR 的要求。但希望通过本文,让大家能对 Web AR 有一定的了解。

参考文档

JChehe avatar May 15 '17 01:05 JChehe