HTML 代码如下
<div class="videoBox" id="videoBox">
<video ref="videoPlayer" width="800" height="600" autoplay muted playsinline></video>
<canvas ref="overlay"></canvas>
</div>
把模型放到 public 文件夹内的 models 文件夹内
引入 face-api.min.js
import "./assets/js/face-api.min.js";
在 created 方法内加载模型
Promise.all([
// 用于人脸检测的高精度模型
faceapi.nets.ssdMobilenetv1.loadFromUri("./models"),
// 用于人脸检测的小型模型,速度快但精度略低
// faceapi.nets.tinyFaceDetector.loadFromUri("./models"),
// 用于检测 68 个面部特征点
faceapi.nets.faceLandmark68Net.loadFromUri("./models"),
// 用于检测 68 个面部特征点的小型模型
// faceapi.nets.faceLandmark68TinyNet.loadFromUri("./models"),
// 用于人脸识别
faceapi.nets.faceRecognitionNet.loadFromUri("./models"),
// 用于估计年龄和性别
faceapi.nets.ageGenderNet.loadFromUri("./models"),
// 用于检测面部表情(如快乐、悲伤、愤怒等)
faceapi.nets.faceExpressionNet.loadFromUri("./models"),
])
.then(() => {
this.$nextTick(() => {
this.startVideo();
});
})
.catch((err) => {
console.error("Error loading models:", err);
});
methods 内的 startVideo 方法
/**
* 初始化视频播放并启动面部检测。
* 此函数旨在开始播放视频,并使用faceapi库对视频中的面部进行检测和标注。
* 它首先获取用户媒体流,然后在视频元素上设置这个流,以便开始播放。
* 随后,它监听视频的播放事件,以便在视频播放时进行面部检测。
*/
startVideo() {
// 获取视频播放器的引用
const videoEl = this.$refs.videoPlayer;
// 请求用户摄像头的媒体流
navigator.mediaDevices.getUserMedia({ video: {} }).then((stream) => {
// 将媒体流设置到视频元素,开始播放
videoEl.srcObject = stream;
});
// 在视频开始播放时执行的操作
videoEl.addEventListener("play", () => {
// 获取覆盖层canvas的引用,用于绘制面部检测的结果
const canvas = this.$refs.overlay;
// 获取视频元素的显示尺寸
const displaySize = { width: videoEl.width, height: videoEl.height };
// 调整canvas的尺寸以匹配视频的显示尺寸
faceapi.matchDimensions(canvas, displaySize);
// 每隔100毫秒进行一次面部检测和绘制
setInterval(async () => {
const options = new faceapi.SsdMobilenetv1Options({
minConfidence: 0.9,
maxResults: 3,
inputSize: 128,
});
// 使用faceapi检测视频中的所有面部,并获取面部标志点
const detections = await faceapi.detectAllFaces(videoEl, options).withFaceLandmarks().withAgeAndGender().withFaceExpressions().withFaceDescriptors();
if (detections.length == 0) {
console.log("未检测到人脸");
} else if (detections.length == 1) {
console.log("检测到一张人脸,置信度:" + detections[0].detection.score);
} else if (detections.length > 1) {
console.log("检测到多张人脸");
}
// 将检测结果调整到与视频相同的尺寸,以便正确绘制
const resizedDetections = faceapi.resizeResults(detections, displaySize);
// 清空canvas以准备新的绘制
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
// 在canvas上绘制面部检测的结果,包括面部边界和标志点
faceapi.draw.drawDetections(canvas, resizedDetections);
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
// 如果不带以下重绘的代码,则仅提示人脸识别的置信度
// 遍历每一次检测的结果,这些结果包含了人脸的年龄、性别、表情等信息
resizedDetections.forEach((detection) => {
// 解构赋值,提取人脸的年龄、性别、性别概率和表情信息
const { age, gender, genderProbability, expressions } = detection;
// 提取人脸检测框的位置信息
const box = detection.detection.box;
// 创建一个新的DrawBox实例,用于在画布上绘制人脸检测框
// 这里通过设置label属性,指定了绘制在检测框周围的文本内容
const drawBox = new faceapi.draw.DrawBox(box, {
label: `
${faceapi.utils.round(age, 0)} years
${gender} (${faceapi.utils.round(genderProbability)})
${Object.entries(expressions).sort((a, b) => b[1] - a[1])[0][0]}
`,
});
// 绘制人脸检测框
drawBox.draw(canvas);
});
}, 100);
});
},
CSS
.videoBox {
width: 600px;
height: 500px;
position: relative;
}
canvas {
position: absolute;
top: 0;
left: 0;
}


其他说明
其中 startVideo方法中的 faceapi内容说明
const options = new faceapi.SsdMobilenetv1Options({
minConfidence: 0.9,
maxResults: 3,
inputSize: 128,
});
// 使用faceapi检测视频中的所有面部,并获取面部标志点
const detections = await faceapi.detectAllFaces(videoEl, options).withFaceLandmarks().withAgeAndGender().withFaceExpressions().withFaceDescriptors();
if (detections.length == 0) {
console.log("未检测到人脸");
} else if (detections.length == 1) {
console.log("检测到一张人脸,置信度:" + detections[0].detection.score);
} else if (detections.length > 1) {
console.log("检测到多张人脸");
}
构造函数调用
faceapi.SsdMobilenetv1Options()
用于配置 SSD MobileNet V1 模型的选项,主要用于人脸检测
需要载入以下模型,用于人脸检测的高精度模型:faceapi.nets.ssdMobilenetv1.loadFromUri("./models")
faceapi.TinyFaceDetectorOptions()
用于配置 Tiny Face Detector 模型的选项。这是一个更轻量级且速度更快的模型,但精度可能略低于 SSD MobileNet V1
需要载入模型,用于人脸检测的小型模型,速度快但精度略低:faceapi.nets.tinyFaceDetector.loadFromUri("./models")
可选配置项
- minConfidence
作用: 控制人脸检测或识别的结果质量。设置较高的 minConfidence 可以确保只有那些模型非常确信的检测结果被接受,从而提高结果的准确性。
取值范围: 通常在 0 到 1 之间,其中 1 表示完全确信,0 表示没有信心。 - maxResults
作用: 设置返回的最大检测结果数量。当检测到多个人脸时,可以限制返回的最大结果数。
取值范围: 通常是一个正整数,表示返回的最大检测结果数量。 - inputSize
作用: 设置输入图像的大小。较大的输入图像通常可以提供更高的检测精度,但会增加计算成本。
取值范围: 通常是一个整数,表示图像的宽度和高度(如 128、224、416 等)。 - scoreThreshold(没测出来怎么用)
作用: 设置检测结果的分数阈值。分数表示模型对每个检测结果的置信度得分,低于此阈值的结果可能会被过滤掉。
取值范围: 通常是一个介于 0 到 1 之间的数值,表示分数的最低接受阈值。
const options = new faceapi.SsdMobilenetv1Options({
minConfidence: 0.9,
maxResults: 5,
inputSize: 128,
});
方法调用
withFaceLandmarks()
用于在检测到的人脸上标记关键点,如眼睛、鼻子、嘴巴等。它在检测人脸位置的基础上,进一步识别面部特征点
需要载入以下模型,用于检测 68 个面部特征点:faceapi.nets.faceLandmark68Net.loadFromUri("./models")或用于检测 68 个面部特征点的小型模型:faceapi.nets.faceLandmark68TinyNet.loadFromUri("./models")
withAgeAndGender()
用于在检测到的人脸上预测年龄和性别。它会返回每个人脸的年龄、性别和性别概率
需要载入以下模型,用于估计年龄和性别:faceapi.nets.ageGenderNet.loadFromUri("./models")
withFaceExpressions()
用于在检测到的人脸上识别情绪表达。它会返回每个人脸的表情及其对应的概率,如快乐、悲伤、愤怒等
需要载入以下模型,用于检测面部表情(如快乐、悲伤、愤怒等):faceapi.nets.faceExpressionNet.loadFromUri("./models")
withFaceDescriptors()
用于提取人脸特征描述符。这些描述符是用于人脸识别的关键数据,可以与已知人脸进行对比,以识别人脸的身份
需要载入以下模型,用于人脸识别:faceapi.nets.faceRecognitionNet.loadFromUri("./models")
1万+

被折叠的 条评论
为什么被折叠?



