系统主要功能包括

  1. 摄像头控制(开启 / 关闭)
  2. 人脸图像捕获
  3. 图像 Base64 编码转换
  4. 与后端 API 通信进行人脸识别
  5. 登录结果处理与用户反馈

核心功能实现

1. 摄像头管理

// 开启摄像头
startCamera() {
  this.tips = "正在开启摄像头...";
  navigator.mediaDevices.getUserMedia({ 
    video: { width: 320, height: 240 }, 
    audio: false 
  })
  .then(stream => {
    this.mediaStream = stream;
    this.video.srcObject = stream;
    this.cameraStarted = true;
    this.tips = "请正对摄像头,点击拍照登录";
  })
  .catch(err => {
    this.error = true;
    this.tips = `摄像头开启失败: ${err.message}`;
    console.error("摄像头错误:", err);
  });
},

// 关闭摄像头
stopCamera() {
  if (this.mediaStream) {
    this.mediaStream.getTracks().forEach(track => track.stop());
    this.mediaStream = null;
    this.video.srcObject = null;
    this.cameraStarted = false;
    this.tips = "摄像头已关闭";
  }
},

这部分代码使用了浏览器的MediaDevices.getUserMedia API 来获取摄像头流,并将其绑定到 video 元素上。

  1. 权限请求:调用 getUserMedia 时,浏览器会弹出权限对话框,用户需手动点击 “允许”310。
  2. 流绑定:获取到的媒体流 stream 直接赋值给 video 元素的 srcObject,实现实时画面显示。
  3. 错误处理:捕获权限拒绝、摄像头不可用等异常,并通过 tips 提示用户。

需要注意的是:

  • 必须在安全上下文(HTTPS 或localhost)中才能访问摄像头
  • 捕获的视频流需要在组件销毁前正确释放,避免资源泄漏
  • 通过track.stop()方法关闭摄像头,这是 HTML5 Media API 的标准用法

navigator.mediaDevices.getUserMedia

navigator.mediaDevices.getUserMedia 是一个Web API,用于请求访问用户的媒体输入设备,如摄像头和麦克风。调用 getUserMedia 时,浏览器会弹出权限对话框,用户需手动点击 “允许”。

绑定到 <video> 

在前端通过 getUserMedia 获取摄像头流后,将其绑定到 <video> 元素的核心原因是利用浏览器原生能力实现实时画面预览

2. 人脸图像捕获与处理

// 拍照并登录
async captureFace() {
  this.loading = true;
  this.error = false;
  this.tips = "正在识别...";
  
  try {
    // 1. 从视频捕获图像
    const ctx = this.canvas.getContext('2d');
    ctx.drawImage(this.video, 0, 0, 320, 240);
    
    // 2. 转换为Base64
    const imageData = this.canvas.toDataURL('image/jpeg').split(',')[1];
    
    // 3. 调用后端API
    const response = await this.$axios.post('/api/face/login', {
      image: imageData
    });
    
    // 4. 处理响应
    if (response.data.code === 200) {
      // 登录成功
      this.$store.commit('SET_USER', response.data.user);
      this.$store.commit('SET_TOKEN', response.data.token);
      this.$message.success('登录成功');
      
      // 延迟跳转,给用户反馈
      setTimeout(() => {
        this.$router.push('/dashboard');
      }, 1000);
    } else {
      // 登录失败
      this.error = true;
      this.tips = `登录失败: ${response.data.message}`;
    }
  } catch (error) {
    this.error = true;
    this.tips = "网络请求失败,请重试";
    console.error("登录错误:", error);
  } finally {
    this.loading = false;
  }
}

这部分代码实现了人脸登录的核心流程:

  1. 使用 Canvas API 从视频流中捕获当前帧图像
  2. 将图像转换为 Base64 编码格式,便于通过 HTTP 传输
  3. 通过 axios 发送 POST 请求到后端人脸识别 API
  4. 根据 API 返回结果处理登录成功或失败的情况

3. 界面交互与状态管理

组件使用了以下数据状态来管理界面交互:

  • cameraStarted:摄像头是否已开启
  • loading:人脸识别过程中显示加载状态
  • error:是否发生错误
  • tips:显示给用户的提示信息

通过这些状态变量,组件实现了:

  • 摄像头控制按钮的启用 / 禁用逻辑
  • 加载状态的视觉反馈
  • 错误提示的显示与样式切换
  • 拍照按钮的状态管理

4. 路由配置与权限控制

// 路由守卫
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !localStorage.getItem('token')) {
    next('/login');
  } else {
    next();
  }
});

这段路由守卫代码实现了基本的身份验证功能:

  • 通过路由元信息meta.requiresAuth标记需要登录才能访问的页面
  • 检查 localStorage 中是否存在 token 来判断用户是否已登录
  • 未登录用户访问受保护页面时会被重定向到登录页

完整流程

 

二、前端流程:图像采集与传输 

1. 摄像头开启与画面预览

技术实现:通过浏览器原生 getUserMedia API 获取摄像头流,并绑定到 <video> 元素。

// 前端代码片段(Vue组件)
startCamera() {
  navigator.mediaDevices.getUserMedia({ 
    video: { width: 320, height: 240 }, 
    audio: false 
  })
  .then(stream => {
    this.video.srcObject = stream; // 显示实时画面
    this.cameraStarted = true;
  })
  .catch(err => {
    console.error("摄像头开启失败:", err);
  });
}

2. 图像捕获与 Base64 编码

  • 触发时机:用户点击「拍照登录」按钮时,通过 <canvas> 捕获当前视频帧。
    captureFace() {
      const ctx = this.canvas.getContext('2d');
      ctx.drawImage(this.video, 0, 0, 320, 240); // 绘制视频帧到canvas
      const imageBase64 = this.canvas.toDataURL('image/jpeg').split(',')[1]; // 转换为Base64(去除data URI前缀)
      return imageBase64;
    }
    

3. 向后端发送识别请求

  • 数据传输:通过 axios 将 Base64 图像数据发送至后端 API。
    const response = await this.$axios.post('/api/face/login', {
      image: imageBase64 // 后端接收参数名为`image`
    });
    

三、后端流程:人脸识别与业务处理

1. 接收请求并调用百度 AI SDK

  • 接口定义:Spring Boot 控制器接收图像数据,初始化百度 AI 客户端。
    // 后端代码片段(Controller)
    @PostMapping("/api/face/login")
    public ResponseEntity<?> faceLogin(@RequestParam String image) {
      try {
        String userId = baiduAiUtils.faceSearch(image); // 调用工具类的人脸搜索方法
        if (userId != null) {
          // 登录成功,生成JWT令牌
          String token = jwtUtils.generateToken(userId);
          User user = userService.getUserByUserId(userId);
          return ResponseEntity.ok(new ResultVO(200, "登录成功", user, token));
        } else {
          return ResponseEntity.badRequest().body(new ResultVO(401, "未找到匹配用户"));
        }
      } catch (Exception e) {
        return ResponseEntity.status(500).body(new ResultVO(500, "人脸识别失败"));
      }
    }
    

2. 人脸搜索核心逻辑(工具类方法)

  • 调用百度 AI 接口:使用 AipFace.search 方法在指定用户组中搜索人脸。
    // 百度AI工具类方法
    public String faceSearch(String imageBase64) {
      try {
        JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);
        if (res.getInt("error_code") == 0) { // API调用成功
          JSONObject result = res.getJSONObject("result");
          JSONArray userList = result.getJSONArray("user_list");
          if (userList.length() > 0) {
            JSONObject user = userList.getJSONObject(0);
            double score = user.getDouble("score");
            if (score > 80) { // 相似度阈值校验
              return user.getString("user_id");
            }
          }
        }
        return null; // 无匹配或得分不足
      } catch (Exception e) {
        log.error("人脸搜索异常:", e);
        return null;
      }
    }
    

3. 业务扩展:用户注册与绑定

  • 首次使用场景:用户需先注册人脸信息到百度 AI 人脸库。
    // 人脸注册方法(工具类)
    public boolean faceRegister(String userId, String imageBase64) {
      JSONObject res = client.addUser(imageBase64, IMAGE_TYPE, GROUP_ID, userId, options);
      return res.getInt("error_code") == 0; // 返回注册结果
    }
    

四、关键技术点解析

1. 图像质量与活体检测

  • 参数控制:通过百度 AI SDK 的 options 配置图像质量和活体检测等级。
    options.put("quality_control", "NORMAL"); // 拒绝低质量图像(模糊、光照不足)
    options.put("liveness_control", "LOW"); // 检测是否为真人(防止照片/视频攻击)
    

2. 安全与性能优化

  • JWT 令牌登录成功后生成令牌,用于后续请求的身份验证,避免频繁查询数据库。
  • HTTPS 传输:确保图像数据在网络传输中加密,防止中间人攻击。
  • 缓存机制:对高频用户的人脸特征值进行本地缓存,减少 API 调用次数。

3. 错误处理与提示

  • 前端反馈:根据后端返回的错误码,显示不同提示(如 “相似度不足”“用户未注册”)。
    // 前端错误处理
    if (response.data.code === 401) {
      this.error = true;
      this.tips = "未找到匹配用户,请先注册人脸";
    } else if (response.data.code === 403) {
      this.tips = "相似度不足,请重新拍照";
    }

 

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐