翻译进度
5
分块数量
2
参与人数

使用 face-api.js 在你的浏览器中做人脸识别(基于 tensorflow.js)

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。


AI

我很兴奋地告诉你,终于可以在浏览器中运行人脸识别了!这篇文章我将介绍 face-api.js ,这个类库构建于  tensorflow.js 之上。它实现了多个 CNNs(卷积神经网络)以解决人脸检测、人脸识别和人脸标识检测的问题,并进行了优化适用于网络和移动设备。

与往常一样,我们将看一个简单的代码示例,演示几行代码就可以使用该软件包。如果您想先尝试一些示例,请查看演示页面! 但不要忘了回来读这篇文章。 ;)

让我们开始吧!

注意,该项目正在积极开发中。请务必查看我的最新文章,随时了解 face-api.js的最新功能:

Summer 翻译于 3周前

如何通过深度学习解决人脸识别

如果您希望尽快入门,您可以跳过这一节,直接跳到代码中。但为了更好地了解face-api.js 中用于实现人脸识别的方法,我强烈建议您继续学习,因为我经常被问到这一点。

简单来讲,我们想要实现的是,根据给定的人脸图像来识别一个人。方法是,为我们想识别的每个人提供一个(或多个)图像,并用人名标记。我们将输入图像与参考数据进行比较,找到 最相似的 参考图像。如果两个图像足够相似,输出 人名,否则输出未知

提起来很容易!然而,还有两个问题。首先,如果我们有一多人的图像,并且我们想识别所有人,那会怎么样?其次,我们需要能够获得两个人脸图像的相似度百分比,以便对它们进行比较……

人脸检测

第一个问题的答案是人脸检测。简单地说,我们将首先定位输入图像中的所有人脸。Face-api.js 为不同的使用情况实现多个人脸检测器。

最准确的人脸检测器是 SSD(单发多框检测器 Single Shot Multibox Detector),它是基于 MobileNet V1 CNN,在网络顶部堆叠了一些附加的框预测层。

更进一步,face-api.js 实现了优化的 Tiny Face Detector,是 Tiny Yolo v2 的甚至更小版本,它利用深度可分离卷积代替常规卷积,与之相比,速度更快,但精度略低 SSD MobileNet V1。

最后,还有一个MTCNN(多任务级联卷积神经网络)实现,但是现在主要用于实验目的。

网络会返回每个面孔的边界框,以及相应的得分,例如每个边界框显示一张脸的概率。分数用于过滤边界框,因为图像可能根本不包含任何面孔。请注意,即使只有一个人,也应该执行面部检测以检索边界框。

人脸标志检测和人脸对齐

第一个问题解决了!但是,我想指出的是,我们要对齐边界框,以便我们可以在图像提取出来之前,将其传递到面部识别网络,因为这将使面部识别更加准确!

为此,face-api.js 实现了一个简单的 CNN,该 CNN 返回给定面部图像的 68 点面部界标

从界标位置开始,边界框可以在面部居中。在下面,您可以看到人脸检测的结果(左)与对齐的人脸图像(右)的比较:

人脸识别

现在,我们可以将提取和对齐的人脸图像馈送到人脸识别网络中,该网络基于类似于 ResNet-34 的体系结构,基本上对应于在 dlib 中实现的体系结构。 该网络经过训练,学会将人脸特征映射到 人脸描述符 (128个值的特征向量),这通常也被称为人脸嵌入。

接下来回到我们最初比较两个人脸的问题:我们将使用每个提取到的人脸描述符,将它们与参考数据的人脸描述符进行比较。更准确地说,我们可以计算两个人脸描述符之间的 欧几里得度量(euclidean distance),并根据 阈值(threshold value) 判断两个人脸是否相似(对于150 x 150大小的人脸图像0.6是一个很好的阈值)。使用 欧几里得度量 效果出奇的好,当然你可以使用任何分类器。下面的 gif 通过欧几里得度量将两个人脸图像的比较可视化:

AI

现在,我们已经掌握了面部识别理论,现在可以开始编写示例了。

Summer 翻译于 3周前

码代码!

在这个简短的示例中,我们将逐步显示如何在以下显示多人的输入图像上进行人脸识别:

AI

脚本

首先,从dist / face-api.jsdist/face-api.min.js 获取最新版本并包含以下脚本:

<script src="face-api.js"></script>

如果您使用npm:

npm i face-api.js

载入模型数据

根据您的应用程序的需求,您可以专门加载所需的模型,但是要运行一个完整的端到端示例,我们将需要加载人脸检测,人脸界标和人脸识别模型。模型文件可在仓库中找到,并可以在这里中找到。

模型权重已量化,与原始模型相比,模型文件大小减少了 75%,从而使您的客户端仅加载所需的最小数据量。此外,模型权重被划分为最大 4 MB 的块,以允许浏览器缓存这些文件,从而使它们仅需加载一次。

模型文件可以简单地以静态资产的形式在您的Web应用程序中提供,也可以将它们托管在其他位置,并且可以通过指定文件的路由或URL来加载。假设您是在 models 目录中提供它们,并在 public / models 下提供资产:

loadModels.js:

const MODEL_URL = '/models'

await faceapi.loadSsdMobilenetv1Model(MODEL_URL)
await faceapi.loadFaceLandmarkModel(MODEL_URL)
await faceapi.loadFaceRecognitionModel(MODEL_URL)
娃哈哈店长 翻译于 3周前

Receive a Full Description for all Faces from an Input Image

The neural nets accept HTML image, canvas or video elements or tensors as inputs. To detect all face’s bounding boxes of an input image we simply say:

computeFullFaceDescriptions.js

const input = document.getElementById('myImage')
let fullFaceDescriptions = await faceapi.detectAllFaces(input).withFaceLandmarks().withFaceDescriptors()

A full face description holds the detecton result (bounding box + score), the face landmarks as well as the computed descriptor. By omitting the second options parameter of faceapi.detectAllFaces(input, options) the SSD MobileNet V1 will be used for face detection by default. To use the Tiny Face Detector or MTCNN instead you can simply do so, by specifying the corresponding options.

For detailed documentation about the face detection options, check out the corresponding section in the readme of the github repo. Note, that you have to load the corresponding model beforehand, for the face detector you want to use as we did with the SSD MobileNet V1 model.

The returned bounding boxes and landmark positions are relative to the original image / media size. In case the displayed image size does not correspond to the original image size you can simply resize them:

fullFaceDescriptions = faceapi.resizeResults(fullFaceDescriptions)

We can visualize the detection results by drawing the bounding boxes into a canvas:

drawDetections.js

faceapi.draw.drawDetections(canvas, fullFaceDescriptions)

The face landmarks can be displayed as follows:

drawLandmarks.js

faceapi.draw.drawLandmarks(canvas, fullFaceDescriptions)

Usually, what I do for visualization, is to overlay an absolutely positioned canvas on top of the img element with the same width and height (see github examples for more info).

Face Recognition

Now that we know how to retrieve the locations and descriptors of all faces given an input image, we will get some images showing one person each and compute their face descriptors. These descriptors will be our reference data.

Assuming we have some example images for our subjects available, we first fetch the images from an url and create HTML image elements from their data buffers using faceapi.fetchImage. For each fetched image we will then locate the subjects face and compute the face descriptor, just as we did previously with our input image:

computeReferenceDescriptors.js

const labels = ['sheldon' 'raj', 'leonard', 'howard']

const labeledFaceDescriptors = await Promise.all(
  labels.map(async label => {
    // fetch image data from urls and convert blob to HTMLImage element
    const imgUrl = `${label}.png`
    const img = await faceapi.fetchImage(imgUrl)

    // detect the face with the highest score in the image and compute it's landmarks and face descriptor
    const fullFaceDescription = await faceapi.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor()

    if (!fullFaceDescription) {
      throw new Error(`no faces detected for ${label}`)
    }

    const faceDescriptors = [fullFaceDescription.descriptor]
    return new faceapi.LabeledFaceDescriptors(label, faceDescriptors)
  })
)

Note, that this time we are using faceapi.detectSingleFace, which will return only the detected face with the highest score, since we assume, that only the character for the given label is shown in that image.

Now, everything that remains to be done is to match the face descriptors of the detected faces from our input image to our reference data, e.g. the labeled face descriptors. For this purpose we can utilize faceapi.FaceMatcher as follows:

faceRecognition.js

// 0.6 is a good distance threshold value to judge
// whether the descriptors match or not
const maxDescriptorDistance = 0.6
const faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, maxDescriptorDistance)

const results = fullFaceDescriptions.map(fd => faceMatcher.findBestMatch(fd.descriptor))

The face matcher uses euclidean distance as a similarity metric, which turns out to work pretty well. We end up with a best match for each face detected in our input image, containing the label + the euclidean distance of the match.
Finally we can draw the bounding boxes together with their labels into a canvas to display the results:

drawResults.js

results.forEach((bestMatch, i) => {
  const box = fullFaceDescriptions[i].detection.box
  const text = bestMatch.toString()
  const drawBox = new faceapi.draw.DrawBox(box, { label: text })
  drawBox.draw(canvas)
})

There we go! By now, I hope you got a first idea how to use the api. Also I’d recommend to take a look at the other examples in the repo. And now, have fun playing around with the package! ;)

If you liked this article you are invited to leave some claps and follow me on medium and/or twitter :). Also feel free to leave a star on the github repository. Stay tuned for more tutorials!

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://itnext.io/face-api-js-javascript...

译文地址:https://learnku.com/ai/t/38827

参与译者:2
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!