微信小程序 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) ,完成「身份证 + 自拍」双重校验功能。

相关推荐
wuhen_n6 小时前
网络请求在Vite层的代理与Mock:告别跨域和后端依赖
前端·javascript·vue.js
用户693717500138410 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦11 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户693717500138411 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水12 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫13 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll12314 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
蓝冰凌15 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛15 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js