广告位 · 页头(后台-模块管理-新建模块后替换此区域)

Vue 3 中如何实现人脸识别?调用百度 AI 接口与摄像头处理详解

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

Vue 3 中如何实现人脸识别?调用百度 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的响应式机制,实现一个基础功能并不困难。你可以基于此扩展出刷脸登录、考勤打卡等实际应用。

广告位 · 文章底部(后台-模块管理替换此区域)