人脸识别在越来越多的Web应用中成为刚需,从考勤打卡到身份核验,前端直接处理摄像头画面并调用云端AI接口是常见的实现方式。Vue 3凭借组合式API和响应式系统,非常适合构建这类交互逻辑。本文将带你一步步完成整个人脸识别流程:调用本地摄像头、获取图像帧、对接百度AI人脸检测接口,并处理返回的人脸位置数据。

一、获取百度AI人脸识别API密钥
百度智能云提供了人脸检测与属性分析接口,使用前需要先注册账号并创建应用。登录百度智能云控制台,进入人脸识别产品页面,点击“创建应用”,填写应用名称和描述。创建成功后,系统会生成三个关键信息:API Key、Secret Key以及对应的AppID。其中API Key和Secret Key用于换取Access Token,而Access Token是调用接口时的身份凭证。
Access Token的有效期为30天,过期后需要重新获取。为了避免频繁请求Token接口,建议将Token缓存在后端或localStorage中,并记录过期时间。获取Access Token的请求地址为https://aip.baidubce.com/oauth/2.0/token,需要携带grant_type=client_credentials、client_id=你的API Key、client_secret=你的Secret Key三个参数。请求成功后返回JSON数据,其中就包含access_token字段。下面的代码展示了在Vue 3项目中如何通过axios获取Token:
// 获取百度AI Access Token
import axios from 'axios';
async function getBaiduToken(apiKey, secretKey) {
const url = 'https://aip.baidubce.com/oauth/2.0/token';
const params = new URLSearchParams();
params.append('grant_type', 'client_credentials');
params.append('client_id', apiKey);
params.append('client_secret', secretKey);
const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
return response.data.access_token;
}
这段代码使用了URLSearchParams构造表单格式的请求体,这是百度接口要求的application/x-www-form-urlencoded格式。返回的Token可以直接用于后续的人脸检测请求。需要注意的是,百度对API Key和Secret Key有调用频率限制,频繁获取Token可能导致被暂时封禁,因此实际项目中建议在服务端统一管理Token的获取和刷新。
二、调用本地摄像头并预览画面
在浏览器中调用摄像头依赖navigator.mediaDevices.getUserMedia接口,该接口返回一个Promise,成功时提供MediaStream对象。在Vue 3组合式API中,我们可以创建一个响应式的视频元素引用,并在组件挂载后请求摄像头权限。由于getUserMedia只在安全上下文(HTTPS或localhost)中可用,部署到生产环境时必须启用HTTPS,否则浏览器会直接拦截请求。
下面是一个完整的摄像头初始化逻辑,包括错误处理:
import { ref, onMounted, onBeforeUnmount } from 'vue';
export default {
setup() {
const videoRef = ref(null);
const stream = ref(null);
const cameraError = ref('');
const initCamera = async () => {
try {
stream.value = await navigator.mediaDevices.getUserMedia({
video: { width: 640, height: 480, facingMode: 'user' },
audio: false
});
if (videoRef.value) {
videoRef.value.srcObject = stream.value;
}
} catch (err) {
cameraError.value = '无法访问摄像头:' + err.message;
}
};
onMounted(initCamera);
onBeforeUnmount(() => {
if (stream.value) {
stream.value.getTracks().forEach(track => track.stop());
}
});
return { videoRef, cameraError };
}
};
模板部分需要放置一个<video>元素,并将ref绑定到videoRef,同时设置autoplay属性让视频自动播放。摄像头打开后,画面会实时显示在页面上。接下来就要从这个视频流中截取一帧图像,转换成Base64格式后发送给百度AI接口。这个操作通常由用户点击按钮触发,比如点击“拍照识别”按钮时执行。
截取图像需要使用<canvas>元素,将视频帧绘制到画布上,然后调用toDataURL方法生成Base64图片数据。为了避免Base64字符串过长导致请求体过大,可以在绘制时适当降低画布分辨率,例如将宽度设为320像素。下面的函数封装了截图逻辑:
function captureFrame(videoElement) {
const canvas = document.createElement('canvas');
const scale = 320 / videoElement.videoWidth; // 缩小到320宽
canvas.width = 320;
canvas.height = videoElement.videoHeight * scale;
const ctx = canvas.getContext('2d');
ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL('image/jpeg', 0.8); // 返回base64
}
三、调用百度人脸检测接口
百度人脸检测接口地址为https://aip.baidubce.com/rest/2.0/face/v3/detect,请求方式为POST,需要在URL后面拼接access_token参数。请求体为JSON格式,包含image(Base64编码的图片数据,需去除data:image/jpeg;base64,前缀)、image_type(固定为BASE64)、face_field(需要返回的人脸属性字段,例如age,beauty,expression,face_shape,gender,glasses,landmark,landmark72,landmark150,quality,eye_status,emotion,face_type)。还可以设置max_face_num限制最大检测人脸数。
在Vue组件中,我们可以将之前的截屏函数与接口请求结合起来。当用户点击按钮后,先获取视频帧的Base64数据,去掉前缀,然后发送请求。下面是一个完整的调用示例:
const detectFace = async () => {
if (!videoRef.value) return;
const base64Data = captureFrame(videoRef.value);
const pureBase64 = base64Data.split(',')[1]; // 去掉前缀
const token = await getBaiduToken(API_KEY, SECRET_KEY);
const url = `https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=${token}`;
const params = {
image: pureBase64,
image_type: 'BASE64',
face_field: 'age,beauty,expression,face_shape,gender,glasses,landmark72,quality,eye_status,emotion,face_type',
max_face_num: 5
};
try {
const response = await axios.post(url, params, {
headers: { 'Content-Type': 'application/json' }
});
console.log('检测结果:', response.data);
// 处理response.data.result.face_list
} catch (err) {
console.error('人脸检测失败:', err);
}
};
注意返回的数据结构:data.result.face_list是一个数组,每个元素包含location(人脸位置坐标),以及face_probability、angle、age、beauty、gender等属性。其中location包括left、top、width、height、rotation,坐标是基于被检测图片的尺寸(也就是我们发送的320宽图片)。如果需要在原始视频上绘制人脸框,需要进行坐标缩放映射。
接口返回的人脸属性中,face_shape表示脸型(如square、triangle、oval等),expression分为none、smile、laugh三类,glasses有none、common、sun三个值。这些字段可以根据业务需要展示给用户,或者用于进一步的身份比对。
四、在页面上绘制人脸框与展示属性
得到人脸位置信息后,我们通常希望在人脸周围绘制一个矩形框。由于视频预览画面可能比发送给接口的图片尺寸大,需要根据比例进行缩放。假设视频元素显示宽度为640px,而发送的图片宽度为320px,缩放因子就是2。绘制时可以使用一个绝对定位的<canvas>覆盖在视频上方,或者直接使用div加上边框来实现。
更简单的方法是使用CSS定位的div元素,每次检测到人脸时更新其left、top、width、height样式。下面的代码展示了如何将接口返回的坐标转换为视频上的像素坐标:
const faceBoxStyle = ref(null);
const updateFaceBox = (location) => {
// 假设视频显示宽度640,发送图片宽度320
const scaleX = videoRef.value.clientWidth / 320;
const scaleY = videoRef.value.clientHeight / (320 * (videoRef.value.videoHeight / videoRef.value.videoWidth));
faceBoxStyle.value = {
left: location.left * scaleX + 'px',
top: location.top * scaleY + 'px',
width: location.width * scaleX + 'px',
height: location.height * scaleY + 'px'
};
};
在模板中,我们可以放置一个div并绑定:style="faceBoxStyle",设置绝对定位、边框颜色和粗细。如果检测到多张人脸,则需要使用数组来存储多个框。此外,还可以将检测出的人脸属性(如年龄、性别、颜值评分)显示在框旁边,提升用户体验。
五、常见坑点与优化建议
开发过程中有几个容易踩的坑需要特别注意。首先是HTTPS限制,getUserMedia只在安全上下文中运行,如果你在IP地址或HTTP环境下测试,摄像头权限会被拒绝。本地开发可以通过localhost访问,或使用自签名证书配置HTTPS。其次是Base64体积问题,原始摄像头画面通常较大,如果直接发送全分辨率图像,请求体可能达到数MB,导致请求缓慢甚至超时。建议在截取帧时降低分辨率,并设置JPEG压缩质量在0.6~0.8之间,以平衡识别准确率和传输性能。
跨域问题也需要关注。百度AI接口支持CORS,前端可以直接用axios请求,但如果你的项目通过代理服务器转发,需要确保代理正确设置了请求头。另外,Access Token的获取建议不要在浏览器端频繁执行,因为API Key和Secret Key会暴露在前端代码中,存在安全风险。更安全的做法是由后端代理获取Token并缓存,前端只调用后端提供的识别接口,这样还可以隐藏API密钥。
性能优化方面,避免每次检测都重新获取Token,可以将Token存储在内存或sessionStorage中,并设置定时刷新。对于摄像头预览,可以使用requestVideoFrameCallback(如果浏览器支持)来按需截取帧,而不是持续截屏。另外,如果同时对多帧进行连续检测,应当限制请求频率,例如使用防抖或节流,防止触发百度接口的QPS限制。
以上就是在Vue 3中集成百度AI人脸识别的完整流程。从申请密钥、调用摄像头、截图编码到发送请求和绘制结果,每一步都包含了可运行的代码示例。虽然人脸识别看似复杂,但借助百度AI的云端能力和Vue 3的响应式机制,实现一个基础功能并不困难。你可以基于此扩展出刷脸登录、考勤打卡等实际应用。

