利用JavaScript在Web应用中轻松实现人脸检测功能

发表时间: 2019-07-16 09:52

想要实现一个面部识别的功能究竟该怎么做?在本文中,我们将以 JavaScript 库 pico.js 为依托,手把手教你如何为一款应用添加面部检测功能。

作者 | Jonathan Freeman

译者 | 弯月,责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

以下为译文:

在本文中,我们将使用pico.js添加简单的面部检测。Pico.js是一个很小的JavaScript库,目前它还是一个近似于概念验证的库,还不能用于生产环境,但在我研究过的人脸检测库中,Pico.js的效果最佳。

本文的目标首先是在地图上通过一个红点显示用户的头部位置:

首先,我们创建一个包含pico.js功能的简单React类,然后用它来获取用户脸部的位置:

<ReactPico onFaceFound={(face) => {this.setState({face})}} />

接下来,如果检测到面部,我们就使用其位置信息来渲染组件:

{face && <FaceIndicator x={face.totalX} y={face.totalY} />}

我们在使用pico.js时所面临的第一个难题是,它是JavaScript的研究项目的实现,不一定是遵循现代JavaScript标准的面向生产环境的库。除此之外,你还不能直接使用yarn add picojs。虽然pico.js的入门教程是一个很好的入门级别的对象检测,但这个教程更像是一篇研究论文而不像API文档。但是,其中提供的示例足够代码使用。我花了几个小时将该教程提供的样本代码放入了一个相对简单的React类中。

pico.js需要做的第一件事就是加载级联模型,该模型会进行一个AJAX调用,而这个调用会引入预先训练好的模型的二进制文件。(你也可以使用pico.js来检测其他类型的对象,但你需要使用官方的pico实现来自己训练模型。)我们可以在componentDidMount方法中加载模型。为了清楚起见,我进一步将示例代码抽象为另一个名为loadFaceFinder的方法:

componentDidMount {
this.loadFaceFinder;
}
loadFaceFinder {
const cascadeurl = 'https://raw.githubusercontent.com/nenadmarkus/pico/c2e81f9d23cc11d1a612fd21e4f9de0921a5d0d9/rnt/cascades/facefinder';
fetch(cascadeurl).then((response) => {
response.arrayBuffer.then((buffer) => {
var bytes = new Int8Array(buffer);
this.setState({
faceFinder: pico.unpack_cascade(bytes)
});
new camvas(this.canvasRef.current.getContext('2d'), this.processVideo);
});
});
}

除了获取和解析人脸检测模型的二进制文件并设置到state中之外,我们还创建了一个新的camvas,它引用了<canvas>上下文和一个回调处理程序。camvas库从用户的网络摄像头将视频加载到canvas上,并针对渲染的每一帧调用处理程序。loadFaceFinder的代码几乎与pico.js提供的参考项目相同。我们只是更改了存储模型的位置,以便可以利用state访问,我们通过React的Ref(而不是使用浏览器提供的DOM API)来引用我们的canvas上下文。

我们的this.processVideo也几乎与参考项目中提供的代码相同。我们只需要稍微做一些改动。我们希望只在加载模型时执行代码,因此我们在代码的整个主体外又添加一个检查。我还用我们希望用户传入的回调处理程序创建了这个React类,因此只有在定义了该处理程序时,才会运行处理代码:

processVideo = (video, dt) => {
if(this.state.faceFinder && this.props.onFaceFound) {
/* all the code */
}
}

我只改动了一个地方:在检测到面部时作何处理。pico.js示例在canvas绘制了一些圆圈,但我们希望将数据传递回我们的回调处理程序。让我们稍微修改一下代码, 以方便我们的回调处理程序更容易地处理这些值:

 this.props.onFaceFound({
x: 640 - dets[i][1],
y: dets[i][0],
radius: dets[i][2],
xRatio: (640 - dets[i][1]) / 640,
yRatio: dets[i][0] / 480,
totalX: (640 - dets[i][1]) / 640 * window.innerWidth,
totalY: dets[i][0] / 480 * window.innerHeight,
});

这种格式允许我们传回在捕获到的canvas元素中面部的绝对位置和半径,面部相对于canvas元素的相对位置,以及面部相对于canvas元素的位置映射到整个页面后的位置。到这里我们自定义的类就基本完成了。接下来,我还需要对pico.js和pico版本的camvas.js进行一些小改动才能使用现代语法,但这些只是关键字的变化,不涉及逻辑关系。

现在,我们可以将我们的自定义ReactPico类导入到我们的应用程序中,渲染,并在我们检测到面部时有条件地渲染FaceIndicator类。在尝试了其他一些人脸检测库之后,我很惊喜地发现pico.js的准确性和可用性非常高,尽管它还不是一个完全成熟的库。

原文:https://www.infoworld.com/article/340301
9/javascript-tutorial-add-face-detection-to-your-web-
app.html

本文为 CSDN 翻译,转载请注明来源出处。

【End】