感谢阿里巴巴资深前端工程师柏子的投稿。
本文将简单讲述图像追踪的原理和如何用JS+WebRTC实现带追踪的AR。
[点击原文链接,查看视频]
GitHub地址
上一篇文章讲了如何在Web端实现图像识别,但我们认知中的AR通常还包括追踪技术,也就是把虚拟的模型定位到现实场景中。在演示视频中,绘制全部采用2D Canvas API ,先绘制WebRCT得到的背景,然后计算出Marker的变化矩阵,接下来把动画绘制到Canvas上。伪代码如下
// 绘制相机视频
ctx.drawImage(bg, 0, 0);
ctx.save();
let [ a, c, e, b, d, f ] = posMatrix;
ctx.transform(a, b, c, d, e, f);
// 绘制动画视频
ctx.drawImage(mv, 0, 0, mv.videoWidth, mv.videoHeight, 0, 0, markerWidth, markerHeight);
ctx.restore();
要实现定位主要有以下步骤:特征点提取 ->特征点匹配 -> 计算变化矩阵
图片特征点提取:
有些长得好看的人,无论穿什么马甲,总能在人群中一眼被认出来(长得难看的人也会被一眼扔出去)
图片也是这样的,有些点特别明显,无论怎么变化(旋转,缩放),总是能被稳定地找出来
以上gif是计算图片的特征点,每次旋转图片,计算新的特征点(红色),有些特征点不受旋转影响,总是能被找到。越复杂的算法,找出的特征点越稳定。
找出一张图片的特征点之后,算法会给每个特征点计算一个类似“ID”的值,ID和特征点是一一对应的,可以通过ID来判断特征点,在两张图片中,我们把ID最相近的两个点匹配在一起,当成同一个特征点。
当然如果两个ID相差很远,那么也不能把这两个点当成同一个特征点,而是抛弃这两个特征点。
如果图片只发生移动而没有缩放旋转,特征点A,在图一的位置是(x1,y1)而在图二的位置变成了(x2,y2),我们就可以计算出图一到图二的图像变化(x2-x1,y2-y1)。上图中明显还发生了旋转,和缩放。所以需要多个特征点进行计算,计算出来的结果可以是三维矩阵或者四维矩阵。
在AR追踪时,预先计算好Marker的特征点和特征点ID,对于摄像机每一帧的照片,计算出每张照片的所有特征点,通过特征点ID匹配,找到Marker在照片的位置,并且在这个位置上绘制图形或者模型。
这些图片匹配的算法都很经典,从opencv里面信手拈来,有人把opencv里面一部分算法写成了js版本(最简单的那一部分-.-),使用JS也能进行图像追踪,JSFeat这个库好几年前就写了,不过可能那几年AR还没有进入大众视野。使用这个库可以完成以上说的寻找特征点,特征点匹配和计算变化矩阵,具体可以参考Demo的代码
一般来说,越稳定的识别算法,对性能要求越高。
首先每张图要从几百万的像素里反复计算,找出几百个特征点
这几百个特征点又要计算ID并且和另一张图的几百个特征点进行距离计算
当匹配了两张图的特征点之后,这些特征点还要拟合出误差最小的变化矩阵
在这几步下,JS的计算能力捉襟见肘,轻轻松松跌破30帧。纯JS无法完成的情况下,要么借助Native计算,要么使用WebAssembly,这两个都不是很容易...
视频中展示的demo是在iOS11下用iPhone7运行480*640分辨率的效果,明显看出有丢帧的情况,主要原因还是特征点识别不稳定,需要更稳定的算法和更强的计算力支撑。
再提供一个SIFT的算法介绍,供大家深度学习。也欢迎大家留言讨论图像算法,如何在Web环境运行复杂的图像算法。更欢迎各位耐心看到这里的工程师们点个赞!