使用 JavaScript 进行人脸识别
人脸检测是人工智能最常见的应用之一。近几年,人脸检测的使用量不断增加。
Face-api.js 带来了一个 JavaScript API,用于在浏览器中进行人脸检测和人脸识别,该 API 在 tensorflow.js 核心 API 之上实现
在本教程中,我们将构建一个可在浏览器中运行的人脸识别应用程序。通过人脸识别,我们将预测用户的情绪、性别和年龄。
项目步骤
步骤1 - 创建一个名为face-recognition
在该文件夹下face-recognition
创建以下文件夹结构
除了模型文件夹外,其他文件夹都一目了然。模型文件夹我会在后面讲解。
步骤2 - 下载face-api.min.js
face-api.min.js
从以下 URL下载代码并将其粘贴到js/face-api.min.js
文件中。
https://raw.githubusercontent.com/karkranikhil/face-recognition-using-js/master/js/face-api.min.js
步骤3-下载模态文件
模型是经过训练的数据,我们将使用它来检测面部特征。
从以下 URL 下载文件并将其放置在models
文件夹中。
https://github.com/karkranikhil/face-recognition-using-js/tree/master/models
步骤4-让我们构建index.html
文件。
在index.html
文件中,我们导入了style.css
样式文件,face-api.min.js
用于处理模型数据和提取特征,以及用于编写逻辑的 main.js 文件。在标签
内部,body
我们创建了一个视频标签来获取人脸,result-container
以显示表情、性别和年龄。
将以下代码放入index.html
文件中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Face recognition App</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<header>Face recognition in the browser using Javascript</header>
<div class="container">
<video id="video" height="500" width="500" autoplay muted></video>
</div>
<div class="result-container">
<div id="emotion">Emotion</div>
<div id="gender">Gender</div>
<div id="age">Age</div>
</div>
<script src="./js/face-api.min.js"></script>
<script src="./js/main.js"></script>
</body>
</html>
步骤5-让我们构建main.js
文件。
在文件中,main.js
我们用于promise.all
将模型加载到人脸 API。一旦 Promise 得到解决,我们就会调用startVideo
启动流式传输的方法。以下是此演示中使用的方法
-
faceapi.detectSingleFace
方法 -detectSingleFace
使用 SSD Mobilenet V1 人脸检测器。您可以通过传递相应的选项对象来指定人脸检测器。要检测多个人脸,请将 替换detectSingleFace
为detectAllFaces
-
withFaceLandmarks method
- 用于检测 68 个面部标志点 -
withFaceExpressions method
- 此方法检测图像中的所有面部+识别每个面部的面部表情并返回数组 -
withAgeAndGendermethod
- 此方法检测图像中的所有面部+估计年龄并识别每个面部的性别并返回数组
将以下代码替换为main.js
const video = document.getElementById("video");
const isScreenSmall = window.matchMedia("(max-width: 700px)");
let predictedAges = [];
/****Loading the model ****/
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri("/models"),
faceapi.nets.faceLandmark68Net.loadFromUri("/models"),
faceapi.nets.faceRecognitionNet.loadFromUri("/models"),
faceapi.nets.faceExpressionNet.loadFromUri("/models"),
faceapi.nets.ageGenderNet.loadFromUri("/models")
]).then(startVideo);
function startVideo() {
navigator.getUserMedia(
{ video: {} },
stream => (video.srcObject = stream),
err => console.error(err)
);
}
/****Fixing the video with based on size size ****/
function screenResize(isScreenSmall) {
if (isScreenSmall.matches) {
video.style.width = "320px";
} else {
video.style.width = "500px";
}
}
screenResize(isScreenSmall);
isScreenSmall.addListener(screenResize);
/****Event Listeiner for the video****/
video.addEventListener("playing", () => {
const canvas = faceapi.createCanvasFromMedia(video);
let container = document.querySelector(".container");
container.append(canvas);
const displaySize = { width: video.width, height: video.height };
faceapi.matchDimensions(canvas, displaySize);
setInterval(async () => {
const detections = await faceapi
.detectSingleFace(video, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceExpressions()
.withAgeAndGender();
const resizedDetections = faceapi.resizeResults(detections, displaySize);
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
/****Drawing the detection box and landmarkes on canvas****/
faceapi.draw.drawDetections(canvas, resizedDetections);
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
/****Setting values to the DOM****/
if (resizedDetections && Object.keys(resizedDetections).length > 0) {
const age = resizedDetections.age;
const interpolatedAge = interpolateAgePredictions(age);
const gender = resizedDetections.gender;
const expressions = resizedDetections.expressions;
const maxValue = Math.max(...Object.values(expressions));
const emotion = Object.keys(expressions).filter(
item => expressions[item] === maxValue
);
document.getElementById("age").innerText = `Age - ${interpolatedAge}`;
document.getElementById("gender").innerText = `Gender - ${gender}`;
document.getElementById("emotion").innerText = `Emotion - ${emotion[0]}`;
}
}, 10);
});
function interpolateAgePredictions(age) {
predictedAges = [age].concat(predictedAges).slice(0, 30);
const avgPredictedAge =
predictedAges.reduce((total, a) => total + a) / predictedAges.length;
return avgPredictedAge;
}
步骤6-让我们将样式添加到应用程序。
style.css
用以下代码替换。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
height: 100vh;
background: #2f2f2f;
width: calc(100% - 33px);
}
canvas {
position: absolute;
}
.container {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
}
.result-container {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
flex-direction: column;
}
.result-container > div {
font-size: 1.3rem;
padding: 0.5rem;
margin: 5px 0;
color: white;
text-transform: capitalize;
}
#age {
background: #1e94be;
}
#emotion {
background: #8a1025;
}
#gender {
background: #62d8a5;
}
video {
width: 100%;
}
header {
background: #42a5f5;
color: white;
width: 100%;
font-size: 2rem;
padding: 1rem;
font-size: 2rem;
}
步骤 7 - 让我们通过实时服务器运行应用程序或http-server
您可以使用以下 URL 运行我部署的应用程序
https://face-recognition.karkranikhil.now.sh/
参考
https://github.com/justadudewhohacks/face-api.js/
GITHUB - https://github.com/karkranikhil/face-recognition-using-js