目录
设置服务器
设置HTML
获取实时视频源
使用face-api.js进行预测
将代码放在一起
测试结果
下一步是什么?
面部表情识别是图像识别中关注的关键领域之一,一直都在更新中,但是训练步骤对于使其能够投入生产是一个很大的障碍。为了克服这一障碍,让我向您介绍face-api.js,这是在TensorFlow.js之上实现的基于JavaScript的人脸识别库。
Face-api.js功能强大且易于使用,仅使您了解配置所需的内容。它实现了多个卷积神经网络(CNN),但隐藏了编写神经网络的所有底层,以解决人脸检测、识别和特征点检测。您可以在此处获取库和模型。
在深入研究任何代码之前,我们需要设置服务器。
如果您一直在看本系列文章,您会发现我们通过直接使用浏览器而不是设置服务器来使事情变得简单。到目前为止,这种方法已经奏效,但是如果我们尝试将face-api.js模型直接提供给浏览器,则会遇到错误,因为HTML5要求我们提供来自Web服务器的网页和图像。
设置服务器的一种简单方法是为Chrome设置Web服务器。启动服务器并进行如下设置
现在,您可以访问http://127.0.0.1:8887来访问您的应用程序。
设置服务器后,创建一个HTML文档并导入face-api库:
我们还需要包含一个视频标签和JavaScript文件来处理我们应用的逻辑。这是文档的最终外观:
Real-Time grumpiness Detection using face-api.js
Loading
让我们转到我们的JavaScript文件并定义一些重要的变量:
const video = document.getElementById("video");
const text = document.getElementById("prediction");
现在,我们设置函数以开始播放视频:
function startVideo() {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ video: true },
function(stream) {
var video = document.querySelector('video');
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
},
function(err) {
console.log(err.name);
}
);
} else {
document.body.innerText ="getUserMedia not supported";
console.log("getUserMedia not supported");
}
}
您可以像这样从URI加载它们,而不是下载所有模型:
let url = "https://raw.githubusercontent.com/justadudewhohacks/face-api.js/master/weights/";
faceapi.nets.tinyFaceDetector.loadFromUri(url + 'tiny_face_detector_model-weights_manifest.json'),
faceapi.nets.faceLandmark68Net.loadFromUri(url + 'face_landmark_68_model-weights_manifest.json'),
faceapi.nets.faceRecognitionNet.loadFromUri(url + 'face_recognition_model-weights_manifest.json'),
faceapi.nets.faceExpressionNet.loadFromUri(url + 'face_expression_model-weights_manifest.json')
Face-api.js将情绪分为七个类别:快乐、悲伤、愤怒、恶心、恐惧、中立和惊讶。由于我们对两个主要类别(中性和脾气暴躁)感兴趣,因此我们将设置top_prediction为中性。一个人在悲伤、生气或厌恶时通常被认为是脾气暴躁的,因此,如果这些情绪中任何一种的预测得分大于中性情绪的预测得分,那么我们会将预测的情绪显示为脾气暴躁。让我们以字符串格式获得最重要的预测:
function prediction_string(obj) {
let top_prediction = "neutral";
let maxVal = 0;
var str = top_prediction;
if (!obj) return str;
obj = obj.expressions;
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
if (obj[p] > maxVal) {
maxVal = obj[p];
top_prediction = p;
if (p===obj.sad || obj.disgusted || obj.angry){
top_prediction="grumpy"
}
}
}
}
return top_prediction;
}
最后,我们需要实际从face-api模型获得预测:
const predictions = await faceapi
.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceExpressions();
最终代码如下所示:
const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const text = document.getElementById("prediction");
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
faceapi.nets.faceExpressionNet.loadFromUri('/models'),
]).then(startVideo);
function prediction_string(obj) {
let top_prediction = "neutral";
let maxVal = 0;
var str = top_prediction;
if (!obj) return str;
obj = obj.expressions;
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
if (obj[p] > maxVal) {
maxVal = obj[p];
top_prediction = p;
if (p===obj.sad || obj.disgusted || obj.angry){
top_prediction="grumpy"
}
}
}
}
return top_prediction;
}
function startVideo() {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ video: true },
function(stream) {
var video = document.querySelector('video');
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
},
function(err) {
console.log(err.name);
}
);
} else {
document.body.innerText ="getUserMedia not supported";
console.log("getUserMedia not supported");
}
}
video.addEventListener("play", () => {
let visitedMsg = true;
setInterval(async () => {
const predictions = await faceapi
.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceExpressions();
if (visitedMsg) {
text.innerText = "Your expression";
visitedMsg = false;
}
text.innerHTML = prediction_string(predictions[0]);
}, 100);
});
现在,在Chrome Web服务器(或您选择的任何其他网络服务器)中运行您的应用。对于Chrome Web Server,请访问http://127.0.0.1:8887以查看您的应用程序的运行情况。
既然我们已经看到使用face-api.js预测人的面部表情有多么容易,我们可以做更多的事情吗?在下一篇文章中,我们将在浏览器中预测某人的性别和年龄。