微信小程序 VisionKit 实战(二):静态图片人脸检测与人像区域提取

一、前言

微信小程序实现身份证识别与裁剪(基于 VisionKit)

在许多小程序场景中,身份证识别只是第一步,提取证件照人像 才是最终目的。

例如:

  • 实名认证时提取身份证头像;
  • 智能证件照生成;
  • 自动对比身份证照片与自拍人脸。

本文将介绍如何使用小程序 VisionKit 提供的 face 模块,完成静态图片人脸检测,并计算出头像的可视区域,实现精准截取。


二、核心逻辑与完整封装

我们先来看核心文件:utils/faceDetector.js

📘 完整代码

javascript 复制代码
/**
 * utils/faceDetector.js
 * 静态图片人脸检测封装
 */

/**
 * 初始化 VKSession
 */
function createVKSession(gl) {
  const session = wx.createVKSession({
    track: {
      face: { mode: 2 }, // 静态图片模式
    },
    version: "v1",
    gl,
  })
  return session
}

/**
 * 静态图片人脸检测
 * @param {Object} options
 * @param {string} options.imgUrl 本地图片路径
 * @param {number} options.width 图片宽
 * @param {number} options.height 图片高
 * @returns {Promise<Object>} 返回人脸框信息和关键点
 */
function detectFace({ imgUrl, width, height, gl }) {
  return new Promise(async (resolve, reject) => {
    try {
      const session = createVKSession(gl)
      const canvas = wx.createOffscreenCanvas({ type: "2d", width, height })
      const ctx = canvas.getContext("2d")

      const img = canvas.createImage()
      await new Promise((r) => {
        img.onload = r
        img.src = imgUrl
      })

      // 绘制图像
      ctx.clearRect(0, 0, width, height)
      ctx.drawImage(img, 0, 0, width, height)
      const imgData = ctx.getImageData(0, 0, width, height)

      // 监听识别结果
      session.on("updateAnchors", (anchors) => {
        if (anchors && anchors.length) {
          const faceData = anchors.map((a) => ({
            origin: a.origin,   // 左上角坐标(归一化 0~1)
            size: a.size,       // 宽高(归一化)
            points: a.points,   // 关键点(五官坐标)
          }))
          resolve(faceData)
        } else {
          reject("未识别到人脸")
        }
      })

      // 启动检测
      session.start(() => {
        session.detectFace({
          frameBuffer: imgData.data.buffer,
          width,
          height,
          scoreThreshold: 0.5,
          sourceType: 1, // 静态图片
          modelMode: 1,
        })
      })
    } catch (err) {
      reject(err)
    }
  })
}

module.exports = { detectFace }

三、使用示例

身份证识别完成后,我们会获得身份证的矫正图(cropImg)及其宽高信息。

接下来调用 detectFace() 即可检测身份证上的人脸区域。

arduino 复制代码
const faceData = await detectFace({
  imgUrl: detectIdCardInfo.cropImg,
  width: detectIdCardInfo.affineImgWidth,
  height: detectIdCardInfo.affineImgHeight,
  gl: this.gl,
})
this.computeFaceRegion(faceData[0], detectIdCardInfo)

四、人像区域计算与裁剪

人脸检测返回的坐标是归一化坐标(0~1) ,所以我们需要根据身份证图像的实际像素宽高换算出真实坐标。

下面是完整实现:

ini 复制代码
// 计算身份证人像完整区域的显示坐标
async computeFaceRegion(faceData, detectIdCardInfo) {
  const fixWidth = 375
  const expandRatioX = 1.4 // 宽度扩展比例
  const expandRatioY = 1.7 // 高度扩展比例

  const { cropImg, affineImgWidth, affineImgHeight } = detectIdCardInfo
  const fixHeight = (fixWidth / affineImgWidth) * affineImgHeight

  const originX = faceData.origin.x
  const originY = faceData.origin.y
  const width = faceData.size.width
  const height = faceData.size.height

  // 扩展人脸区域(避免裁切过紧)
  const newX = Math.max(originX - ((expandRatioX - 1) / 2) * width, 0)
  const newY = Math.max(originY - ((expandRatioY - 1) / 2) * height, 0)
  const newWidth = Math.min(width * expandRatioX, 1 - newX)
  const newHeight = Math.min(height * expandRatioY, 1 - newY)

  // 向上微调,让头像居中
  const moveUpRatio = 0.1
  const faceBoxTop = Math.max(newY * fixHeight - newHeight * fixHeight * moveUpRatio, 0)

  const faceRegion = {
    faceImgUrl: cropImg,
    faceImgWidth: fixWidth,
    faceImgHeight: fixHeight,
    faceBoxLeft: newX * fixWidth,
    faceBoxTop,
    faceBoxWidth: newWidth * fixWidth,
    faceBoxHeight: newHeight * fixHeight,
  }

  this.setData({ ...faceRegion })

  // 调用裁剪逻辑
  const cropResult = await cropFace(cropImg, faceRegion)
  this.setData({ cropUrl: cropResult.tempFilePath, cropBase64: cropResult.base64 })
}

这样就能从身份证中自动提取头像区域,生成标准证件照。


五、逻辑总结

模块 功能 说明
createVKSession 初始化 VisionKit 会话 指定人脸检测模式(静态图片)
detectFace 调用 VisionKit 识别人脸 返回人脸框坐标与五官关键点
computeFaceRegion 根据人脸框计算裁剪区域 支持扩展、上移、缩放调整
cropFace Canvas 裁剪函数 最终生成证件照或头像图

六、原理概述:VisionKit 人脸识别模块

VisionKit 是微信小程序提供的视觉识别能力,支持包括:

功能 模式
人脸检测 (face) 实时 / 静态
身份证识别 (IDCard) 照片模式
姿态估计 (body) 实时人体识别

在本例中,我们使用了:

css 复制代码
track: { face: { mode: 2 } }

代表静态图片模式,适合身份证头像识别、图片对比等场景。


七、结语

通过本文的封装与分析,我们实现了从身份证识别 → 人脸检测 → 头像提取的完整链路。

下一篇我们将进一步扩展,介绍如何利用识别结果进行 人脸对比验证(Face Compare) ,完成「身份证 + 自拍」双重校验功能。

相关推荐
左耳咚1 分钟前
如何解析 zip 文件
前端·javascript·面试
程序员小寒11 分钟前
前端高频面试题之Vue(初、中级篇)
前端·javascript·vue.js
陈辛chenxin18 分钟前
软件测试大赛Web测试赛道工程化ai提示词大全
前端·可用性测试·测试覆盖率
沿着路走到底20 分钟前
python 判断与循环
java·前端·python
Code知行合壹22 分钟前
AJAX和Promise
前端·ajax
大菠萝学姐32 分钟前
基于springboot的旅游攻略网站设计与实现
前端·javascript·vue.js·spring boot·后端·spring·旅游
心随雨下44 分钟前
TypeScript中extends与implements的区别
前端·javascript·typescript
摇滚侠1 小时前
Vue 项目实战《尚医通》,底部组件拆分与静态搭建,笔记05
前端·vue.js·笔记·vue
双向331 小时前
CANN训练营实战指南:从算子分析到核函数定义的完整开发流程
前端
caleb_5201 小时前
vue cli的介绍
前端·javascript·vue.js