65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 face-api 和 Tensorflow.js 进行预训练的 AI 情绪检测

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2020 年 8 月 21 日

CPOL

2分钟阅读

viewsIcon

12296

downloadIcon

212

在本文中,我们将使用另一个预训练模型 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

设置服务器后,创建一个 HTML 文档并导入 face-api 库

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script type="application/x-javascript" src="face-api.js"></script>

我们还需要包含一个视频标签和 JavaScript 文件来处理我们的应用程序逻辑。这是文档的最终外观

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="application/x-javascript" src="face-api.js"></script>    
  </head>
  <body>
    <h1>Real-Time grumpiness Detection using face-api.js</h1>
    <video autoplay muted id="video" width="224" height="224" style=" margin: auto;"></video>
    <div id="prediction">Loading</div>
  <script type="text/javascript" defer src="index.js"></script>
  </body>
</html>

获取实时视频流

让我们移动到我们的 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");
  }
}

使用 face-api.js 进行预测

您可以像这样从 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 服务器(或您选择的任何其他 Web 服务器)中运行您的应用程序。对于 Chrome Web 服务器,请访问 http://127.0.0.1:8887 以查看您的应用程序的实际效果。

下一步是什么?

现在我们已经了解了使用 face-api.js 预测人类面部表情的简便性,我们还能用它做更多的事情吗?在下一篇文章中,我们将预测浏览器中的性别和年龄。

© . All rights reserved.