Face API(JS)人脸对比HTML应用报错求助:faceapi未定义等问题
人脸对比HTML应用报错排查求助
错误信息
fr-index.html:52 Uncaught (in promise) ReferenceError: faceapi is not defined at loadModels (fr-index.html:52:13) at fr-index.html:83:5 loadModels @ fr-index.html:52 (anonymous) @ fr-index.html:83 Promise.then (anonymous) @ fr-index.html:83 Understand this error index.js:2 Uncaught ReferenceError: exports is not defined at index.js:2:23
问题概述
我正在开发一款可对比摄像头实时人脸与上传人脸相似度的HTML应用,但遇到上述无法解决的错误。我认为这些错误可能与Face API库的加载方式或函数使用有关,以下是我的完整代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Camera Comparison</title> <style> video, canvas, img { max-width: 45%; } canvas { position: absolute; } </style> </head> <body> <h2>Camera</h2> <video id="video" autoplay playsinline></video> <canvas id="canvas"></canvas> <h2>Upload Image</h2> <input type="file" id="imageUpload" accept="image/*" /> <img id="uploadedImage" /> <button id="compareButton">Compare Images</button> <script defer src="https://cdn.jsdelivr.net/npm/face-api.js"></script> <script> const video = document.getElementById("video"); const canvas = document.getElementById("canvas"); const imageUpload = document.getElementById("imageUpload"); const uploadedImage = document.getElementById("uploadedImage"); const compareButton = document.getElementById("compareButton"); let uploadedFaceData; function startVideo() { navigator.mediaDevices .getUserMedia({ video: true }) .then((stream) => { video.srcObject = stream; }) .catch((err) => { console.error("Error accessing the camera: ", err); alert("Could not access the camera."); }); } async function loadModels() { await Promise.all([ faceapi.nets.ssdMobilenetv1.loadFromUri("/models"), faceapi.nets.faceLandmark68Net.loadFromUri("/models"), faceapi.nets.faceRecognitionNet.loadFromUri("/models"), ]); } imageUpload.addEventListener("change", async (e) => { const file = e.target.files[0]; if (file) { const img = await faceapi.bufferToImage(file); uploadedImage.src = img.src; uploadedFaceData = await faceapi .detectSingleFace(img) .withFaceLandmarks() .withFaceDescriptor(); } }); compareButton.addEventListener("click", async () => { const capturedFaceData = await faceapi .detectSingleFace(video) .withFaceLandmarks() .withFaceDescriptor(); if (!uploadedFaceData || !capturedFaceData) { alert("No faces detected in one or both images."); return; } const faceMatcher = new faceapi.FaceMatcher(uploadedFaceData); const result = faceMatcher.findBestMatch( capturedFaceData.descriptor ); alert(result.toString()); }); loadModels().then(startVideo); </script> </body> </html>
修复方案
1. 解决faceapi is not defined错误
问题出在脚本执行顺序:自定义脚本在face-api.js未加载完成时就调用了faceapi对象。即使CDN脚本加了defer,自定义脚本也没等待库加载完成就执行了loadModels()。
修复方式:
将启动逻辑改为等待DOM和库加载完成后执行,替换原代码最后一行:
document.addEventListener('DOMContentLoaded', async () => { await loadModels(); startVideo(); });
或者给自定义脚本也加上defer,确保它在CDN脚本之后执行:
<script defer src="https://cdn.jsdelivr.net/npm/face-api.js"></script> <script defer> // 你的自定义代码... </script>
2. 解决exports is not defined错误
这个错误是因为项目中可能误引入了Node.js环境的模块文件(比如index.js),浏览器不支持exports对象。
修复方式:
检查项目中是否有多余的脚本标签引入了Node.js风格的模块文件,删除或修正这些引入。当前使用的CDN链接是浏览器兼容版本,无需替换。
3. 修复模型加载问题
原代码尝试从/models路径加载模型,但该路径默认不存在,会导致模型加载失败。
修复方式:
- 本地存放模型:从face-api.js官方仓库下载预训练模型(包含
ssd_mobilenetv1、face_landmark_68、face_recognition三个文件夹),放在HTML文件同级的models目录中。 - 或使用CDN加载模型,修改
loadModels函数:
async function loadModels() { await Promise.all([ faceapi.nets.ssdMobilenetv1.loadFromUri("https://cdn.jsdelivr.net/npm/face-api.js/models"), faceapi.nets.faceLandmark68Net.loadFromUri("https://cdn.jsdelivr.net/npm/face-api.js/models"), faceapi.nets.faceRecognitionNet.loadFromUri("https://cdn.jsdelivr.net/npm/face-api.js/models"), ]); }
4. 修正FaceMatcher用法
原代码中new faceapi.FaceMatcher(uploadedFaceData)用法错误,FaceMatcher需要接收带标签的描述符数组。
修复方式:
修改对比按钮的点击事件逻辑:
compareButton.addEventListener("click", async () => { const capturedFaceData = await faceapi .detectSingleFace(video) .withFaceLandmarks() .withFaceDescriptor(); if (!uploadedFaceData || !capturedFaceData) { alert("No faces detected in one or both images."); return; } // 构建带标签的描述符数组 const labeledDescriptors = [ new faceapi.LabeledFaceDescriptors('Uploaded Face', [uploadedFaceData.descriptor]) ]; const faceMatcher = new faceapi.FaceMatcher(labeledDescriptors); const result = faceMatcher.findBestMatch(capturedFaceData.descriptor); alert(`相似度:${result.distance.toFixed(2)},匹配结果:${result.label}`); });
内容的提问来源于stack exchange,提问作者T_Braun
相关产品推荐
相关产品推荐

