
本教程详细阐述了如何使用 face-api.js 在浏览器环境中实现稳定且准确的多目标人脸识别。针对常见的多人脸误识别问题,文章深入分析了 `labeledfacedescriptors` 和 `facematcher` 的正确构建与使用方法,确保每个已知人脸都能被独立且准确地识别,并提供了完整的 svelte 代码示例及优化建议。
在现代 Web 应用中集成人脸识别功能,face-api.js 是一个强大且易于使用的 JavaScript 库。然而,开发者在使用过程中常会遇到一个挑战:当系统需要识别多个已知人脸时,可能会出现所有检测到的人脸都被错误地标记为同一个人的情况,即使“未知”人脸能够被正确识别。本文将深入探讨这一问题,并提供一个健壮的解决方案,确保 face-api.js 能够准确地区分和识别画面中的多个人脸。
问题的核心在于 face-api.js 中 LabeledFaceDescriptors 的构建方式。原始代码可能存在以下逻辑缺陷:
这导致的结果是,当摄像头前出现多个人脸时,face-api.js 虽然能检测到所有面部,但在进行匹配时,由于内部描述符的混淆,它会倾向于将所有已知面孔都识别为第一个或最接近的匹配项,从而出现“只识别一个人”的假象。
要解决上述问题,我们需要正确理解 face-api.js 中的几个核心概念:
这是解决多目标识别问题的关键。faceapi.LabeledFaceDescriptors 类用于将一个特定的人脸描述符数组与一个唯一的标签(如人名)关联起来。它的构造函数是 new faceapi.LabeledFaceDescriptors(label: string, descriptors: Float32Array[])。
faceapi.FaceMatcher 类用于将一个未知人脸的描述符与一组已知的 LabeledFaceDescriptors 进行比较,找出最佳匹配。
解决多目标误识别问题的核心在于确保每个已知人物都拥有独立且正确关联的 LabeledFaceDescriptors 对象。
在原始代码中,getLabeledFaceDescriptions 函数可能将所有客户的描述符都推送到一个名为 descriptions 的全局数组中。随后,在 map 函数内部,针对每个 customer 调用 new faceapi.LabeledFaceDescriptors(customer.name, descriptions)。此时,descriptions 数组已经包含了所有(或部分)客户的描述符,导致每个 LabeledFaceDescriptors 对象都引用了同一个混淆的描述符集合,从而使 FaceMatcher 无法区分不同的人。
我们应该为每个客户创建一个独立的描述符数组,并用该数组来构建其对应的 LabeledFaceDescriptors 对象。
// 假设 $customers 和 $baseURL 是 Svelte store 或可访问的变量
// $customers 结构示例: [{ name: 'Customer A', image_url: '/path/to/a.jpg' }, ...]
async function getLabeledFaceDescriptors(customers, baseURL) {
const labeledDescriptors = await Promise.all(
customers.map(async (customer) => {
if (!customer.image_url) {
console.warn(`Customer ${customer.name} has no image_url, skipping.`);
return null;
}
const descriptorsForThisCustomer = []; // 为每个客户创建一个独立的描述符数组
// 可以根据需要从多张图片或同一图片的不同检测中获取多个描述符
// 这里假设每位客户有一张图片,从中提取一个描述符
try {
const img = await faceapi.fetchImage(baseURL + customer.image_url);
const detection = await faceapi
.detectSingleFace(img)
.withFaceLandmarks()
.withFaceDescriptor();
if (detection && detection.descriptor) {
descriptorsForThisCustomer.push(detection.descriptor);
} else {
console.warn(`No face detected for ${customer.name} from image: ${baseURL + customer.image_url}`);
}
} catch (error) {
console.error(`Error processing image for ${customer.name}:`, error);
return null;
}
if (descriptorsForThisCustomer.length > 0) {
// 使用该客户专属的描述符数组创建 LabeledFaceDescriptors
return new faceapi.LabeledFaceDescriptors(
customer.name,
descriptorsForThisCustomer
);
}
return null;
})
);
// 过滤掉任何未能成功获取描述符的客户
return labeledDescriptors.filter((d) => d !== null);
}以下是一个完整的 Svelte 组件示例,展示了如何在浏览器中实现多目标人脸识别。
在开始人脸识别之前,需要加载 face-api.js 所需的模型。
// Svelte script context
import { onMount, onDestroy } from 'svelte';
import * as faceapi from 'face-api.js';
let video;
let detections;
let width = 640; // 调整为适合您的视频流尺寸
let height = 480;
let canvas, ctx;
let container;
let faceMatcher; // 全局 FaceMatcher 实例
// 假设 $customers 和 $baseURL 是 Svelte store,需要在实际应用中注入
// 例如: import { customers, baseURL } from './stores';
// 或者通过 props 传递
export let customers = []; // 假设通过 props 传递客户数据
export let baseURL = ''; // 假设通过 props 传递基础 URL
const detectionOptions = {
withLandmarks: true,
withDescriptors: true,
minConfidence: 0.5,
MODEL_URLS: {
Mobilenetv1Model:
"https://raw.githubusercontent.com/ml5js/ml5-data-and-models/main/models/faceapi/ssd_mobilenetv1_model-weights_manifest.json",
FaceLandmarkModel:
"https://raw.githubusercontent.com/ml5js/ml5-data-and-models/main/models/faceapi/face_landmark_68_model-weights_manifest.json",
FaceRecognitionModel:
"https://raw.githubusercontent.com/ml5js/ml5-data-and-models/main/models/faceapi/face_recognition_model-weights_manifest.json",
},
};
onDestroy(() => {
if (video) {
video.pause();
if (video.srcObject) {
video.srcObject.getTracks().forEach(track => track.stop());
}
video.srcObject = null;
video.remove();
}
if (canvas) {
canvas.remove();
}
});
onMount(() => {
initFaceRecognition();
});
// ... (getLabeledFaceDescriptors 函数如上所示) ...
async function initFaceRecognition() {
// 获取视频流
video = await getVideo();
// 创建画布
canvas = createCanvas(width, height);
ctx = canvas.getContext('2d');
// 加载模型
await Promise.all([
faceapi.nets.ssdMobilenetv1.loadFromUri(detectionOptions.MODEL_URLS.Mobilenetv1Model),
faceapi.nets.faceRecognitionNet.loadFromUri(detectionOptions.MODEL_URLS.FaceRecognitionModel),
faceapi.nets.faceLandmark68Net.loadFromUri(detectionOptions.MODEL_URLS.FaceLandmarkModel),以上就是face-api.js 浏览器人脸识别:精确识别多个人脸的实践指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号