如何用摄像头拍照替代文件上传实现faceapi人脸识别?
改造FaceAPI人脸识别为摄像头拍照模式
原代码通过文件上传选择图片进行人脸识别,以下是修改为摄像头拍照获取图像并识别的实现方案:
核心修改点
- 移除文件上传控件,添加视频元素用于实时预览摄像头画面
- 使用
getUserMediaAPI获取摄像头权限并捕获视频流 - 添加拍照按钮,点击时捕获当前视频帧作为识别图像
- 复用原有人脸识别逻辑,适配摄像头捕获的图像
完整代码实现
HTML部分
<body> <!-- 摄像头预览视频 --> <video id="video" width="640" height="480" autoplay muted></video> <!-- 拍照识别按钮 --> <button id="captureBtn">拍照识别</button> <!-- 识别结果展示容器 --> <div id="container" style="position: relative;"></div> </body>
JavaScript部分
const video = document.getElementById('video'); const captureBtn = document.getElementById('captureBtn'); const container = document.getElementById('container'); let faceMatcher; let canvas; // 加载FaceAPI预训练模型 Promise.all([ faceapi.nets.faceRecognitionNet.loadFromUri('/models'), faceapi.nets.faceLandmark68Net.loadFromUri('/models'), faceapi.nets.ssdMobilenetv1.loadFromUri('/models') ]).then(async () => { // 初始化人脸匹配器(依赖你原有的标注人脸加载逻辑) const labeledFaceDescriptors = await loadLabeledImages(); faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, 0.6); // 请求摄像头权限并启动视频流 const stream = await navigator.mediaDevices.getUserMedia({ video: true }); video.srcObject = stream; document.body.append('模型加载完成,点击按钮开始拍照识别'); }); // 拍照触发人脸识别逻辑 captureBtn.addEventListener('click', async () => { // 清除上一次的识别画布 if (canvas) canvas.remove(); // 从当前视频帧生成图像 const tempCanvas = document.createElement('canvas'); tempCanvas.width = video.videoWidth; tempCanvas.height = video.videoHeight; const ctx = tempCanvas.getContext('2d'); ctx.drawImage(video, 0, 0, tempCanvas.width, tempCanvas.height); const image = new Image(); image.src = tempCanvas.toDataURL('image/png'); await new Promise(resolve => image.onload = resolve); // 将图像添加到展示容器 container.append(image); // 创建识别结果绘制画布 canvas = faceapi.createCanvasFromMedia(image); container.append(canvas); // 适配画布尺寸与图像一致 const displaySize = { width: image.width, height: image.height }; faceapi.matchDimensions(canvas, displaySize); // 执行人脸检测与识别 const detections = await faceapi.detectAllFaces(image).withFaceLandmarks().withFaceDescriptors(); const resizedDetections = faceapi.resizeResults(detections, displaySize); const results = resizedDetections.map(d => faceMatcher.findBestMatch(d.descriptor)); // 绘制识别框与标签 results.forEach((result, i) => { const box = resizedDetections[i].detection.box; const drawBox = new faceapi.draw.DrawBox(box, { label: result.toString() }); drawBox.draw(canvas); }); }); // 保留你原有的标注人脸加载函数(需自行实现内部逻辑) async function loadLabeledImages() { // 示例逻辑(替换为你实际的标注图片加载代码) // const labels = ['张三', '李四'] // return Promise.all( // labels.map(async label => { // const descriptors = [] // for (let i = 1; i <= 5; i++) { // const img = await faceapi.fetchImage(`/labeled_faces/${label}/${i}.jpg`) // const detection = await faceapi.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor() // descriptors.push(detection.descriptor) // } // return new faceapi.LabeledFaceDescriptors(label, descriptors) // }) // ) }
注意事项
- 确保
/models目录下存放FaceAPI所需的全部预训练模型文件 - 浏览器需运行在HTTPS环境或localhost下,才能正常调用摄像头API
loadLabeledImages函数需保持原有实现,用于加载已标注的人脸数据以完成匹配
内容的提问来源于stack exchange,提问作者AnonymousAlias
相关产品推荐
相关产品推荐

