2021-07-24 07:25:01
使用 face-api.js 在浏览器中实现精确多目标人脸识别的核心步骤如下:
模型加载与初始化
加载三种关键模型:SSD Mobilenet V1(人脸检测)、Face Landmark 68(关键点检测)、Face Recognition(特征提取)。
示例代码(Svelte 环境):
async function loadModels() { await Promise.all([ faceapi.nets.ssdMobilenetv1.loadFromUri('/models'), faceapi.nets.faceLandmark68Net.loadFromUri('/models'), faceapi.nets.faceRecognitionNet.loadFromUri('/models') ]);}构建独立的 LabeledFaceDescriptors 对象
问题根源:原始代码可能将所有客户的描述符存入全局数组,导致 FaceMatcher 混淆不同人脸。
解决方案:为每个客户创建独立的描述符数组,并关联唯一标签。
关键代码逻辑:
async function getLabeledFaceDescriptors(customers) { return Promise.all(customers.map(async (customer) => { const descriptors = []; const img = await faceapi.fetchImage(customer.imageUrl); const detection = await faceapi.detectSingleFace(img) .withFaceLandmarks() .withFaceDescriptor(); if (detection?.descriptor) descriptors.push(detection.descriptor); return descriptors.length > 0 ? new faceapi.LabeledFaceDescriptors(customer.name, descriptors) : null; })).then(results => results.filter(Boolean));}初始化 FaceMatcher 实例
使用独立的 LabeledFaceDescriptors 数组初始化匹配器,确保每个客户的数据隔离。
示例:
let faceMatcher;async function initFaceMatcher(customers) { const labeledDescriptors = await getLabeledFaceDescriptors(customers); faceMatcher = new faceapi.FaceMatcher(labeledDescriptors, 0.6); // 0.6为距离阈值}实时检测与匹配流程
步骤:
从视频流中捕获帧并绘制到画布。
检测所有人脸并提取描述符。
使用 FaceMatcher 计算最佳匹配结果。
完整检测逻辑:
async function handleFrame() { if (!video || !faceMatcher) return; // 检测人脸 const detections = await faceapi.detectAllFaces(video) .withFaceLandmarks() .withFaceDescriptors(); // 调整画布尺寸并绘制检测结果 const resizedDetections = faceapi.resizeResults(detections, { width, height }); ctx.clearRect(0, 0, width, height); faceapi.draw.drawDetections(canvas, resizedDetections); // 匹配并标注结果 resizedDetections.forEach(detection => { const bestMatch = faceMatcher.findBestMatch(detection.descriptor); if (bestMatch.distance < 0.6) { // 匹配阈值 faceapi.draw.drawText( canvas, bestMatch.toString(), detection.detection.box.x, detection.detection.box.y - 10 ); } }); requestAnimationFrame(handleFrame);}关键优化建议
多角度样本:为每个客户提供3-5张不同角度/表情的照片,提升描述符鲁棒性。
阈值调优:通过实验调整 distanceThreshold(通常0.5-0.7),平衡误识率与漏识率。
性能优化:
使用 detectAllFaces 替代单帧多次调用 detectSingleFace。
限制视频分辨率(如640x480)减少计算量。
错误处理:添加对无人脸、模型加载失败等场景的容错逻辑。
完整实践流程总结: