单样本检测

方法定义

单样本检测(One-shot Detection, OSD)只使用一张待检测类别的图片,就能检测到输入图像中该类别的物体。 待检测类别图片被称为OSD marker。 与一般物体检测不同,OSD 理论上可以检测任意用户指定的类别。该方法允许 OSD marker 与输入图像中的物体有视角差异或一定程度的外形差异。

应用场景示例

  1. 标志性建筑检测。
  2. Logo检测。
  3. 商品检测。
  4. 宠物检测。
  5. 动漫形象检测。

osd移动端演示

能力介绍

  • 使用方法
  1. 添加 OSD marker :调用 VKSession.addOSDMarker() 设置需要检测的物体,例如一张商品图片,返回markerId。说明:
    (1) 可多次调用该函数来添加多张图片,用于检测多种类物体。
    (2) 添加 OSD marker 后就可以持续输入图像来检测物体,不需要每次输入图像前都添加 OSD marker
  2. 删除 OSD marker :调用 VKSession.removeOSDMarker() 根据 markerId 删除对应 OSD marker ,从而不再检测该物体。
  3. 获取当前所有 OSD marker 信息:调用 VKSession.getAllOSDMarker() 得到当前所有 OSD marker 的列表,列表每一项包含了 markerId 和该图片的路径。
  • 程序示例
    可以在 单样本检测(OSD)能力使用参考 页面查看示例代码。

人脸关键点检测

VisionKit 从基础库 2.25.0 版本 (安卓微信>=8.0.25,iOS微信>=8.0.24) 开始提供人脸关键点检测,作为与 marker 能力OSD 能力 平行的能力接口。

从 微信 >= 8.1.0 版本开始提供人脸3D关键点检测,作为人脸2D关键点检测的扩展能力接口。

方法定义

人脸关键点检测有2种使用方法,一种是输入一张静态图片进行检测,另一种是通过摄像头实时检测。

1. 静态图片检测

通过 VKSession.detectFace 接口 输入一张图像,算法检测到图像中的人脸,然后通过 VKSession.on 接口 输出人脸位置坐标、106个关键点坐标以及人脸在三维坐标系中的旋转角度。

示例代码:

const session = wx.createVKSession({
  track: {
    face: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})
// 静态图片检测模式下,每调一次 detectFace 接口就会触发一次 updateAnchors 事件
session.on('updateAnchors', anchors => {
  anchors.forEach(anchor => {
    console.log('anchor.points', anchor.points)
    console.log('anchor.origin', anchor.origin)
    console.log('anchor.size', anchor.size)
    console.log('anchor.angle', anchor.angle)
  })
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
    session.detectFace({
      frameBuffer, // 图片 ArrayBuffer 数据。人脸图像像素点数据,每四项表示一个像素点的 RGBA
      width, // 图像宽度
      height, // 图像高度
      scoreThreshold: 0.5, // 评分阈值
      sourceType: 1,
      modelMode: 1,
    })
  }
})

2. 通过摄像头实时检测

算法实时检测相机中的人脸,通过 VKSession.on 接口 实时输出人脸位置坐标、106个关键点坐标以及人脸在三维坐标系中的旋转角度。

示例代码:

const session = wx.createVKSession({
  track: {
    face: { mode: 1 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 摄像头实时检测模式下,监测到人脸时,updateAnchors 事件会连续触发 (每帧触发一次)
session.on('updateAnchors', anchors => {
  anchors.forEach(anchor => {
    console.log('anchor.points', anchor.points)
    console.log('anchor.origin', anchor.origin)
    console.log('anchor.size', anchor.size)
    console.log('anchor.angle', anchor.angle)
  })
})

// 当人脸从相机中离开时,会触发 removeAnchors 事件
session.on('removeAnchors', () => {
  console.log('removeAnchors')
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
  }
})

3. 开启3D关键点检测

想要开启人脸3D关键点检测能力,静态图片模式仅需要在2D调用基础上增加open3d字段,如下

// 静态图片模式调用
session.detectFace({
      ...,           // 同2D调用参数
      open3d: true,  // 开启人脸3D关键点检测能力,默认为false
    })

摄像头实时模式则在2D调用基础上增加3D开关更新函数,如下

// 摄像头实时模式调用
session.on('updateAnchors', anchors => {
  this.session.update3DMode({open3d: true})  // 开启人脸3D关键点检测能力,默认为false
  ...,  // 同2D调用参数
})

输出说明

1. 点位定义

人脸2D关键点与人脸3D关键点均为106点,定义方式如下图所示。在脸部姿态发生变化时,人脸2D关键点的轮廓点会始终沿着可见人脸边缘,而人脸3D关键点则维持立体结构。

2. 人脸2D关键点

人脸2D关键点输出字段包括

struct anchor
{
  points,    // 106点在图像中的(x,y)坐标
  origin,    // 人脸框的左上角(x,y)坐标
  size,      // 人脸框的宽和高(w,h)
  angle,     // 人脸角度信息(pitch, yaw, roll)
  confidence // 人脸关键点的置信度
}

3. 人脸3D关键点

开启人脸3D关键点检测能力后,可以获取人脸2D及3D关键点信息,其中人脸3D关键点输出字段包括

struct anchor
{ 
  ...,               // 人脸关键点2D输出信息
  points3d,          // 人脸106点的(x,y,z)3D坐标
  camExtArray,       // 相机外参矩阵,定义为[R, T \\ 0^3 , 1], 使用相机内外参矩阵可将3D点位投影回图像
  ccamIntArray       // 相机内参矩阵,参考glm::perspective(fov, width / height, near, far);
}

应用场景示例

  1. 人脸检测。
  2. 人脸特效。
  3. 人脸姿态估计。
  4. 人脸 AR 游戏。

程序示例

  1. 实时摄像头人脸检测能力使用参考
  2. 静态图像人脸检测能力使用参考

特别说明

微信小程序人脸识别功能涉及采集、存储用户生物特征(如人脸照片或视频、身份证和手持身份证、身份证照和免冠照等),此类型服务需使用微信原生人脸识别接口

Body检测

VisionKit从基础库 2.28.0版本开始提供body检测能力。从 微信>=8.1.0 版本开始提供人体3D关键点检测,作为Body检测的扩展能力接口。

方法定义

body检测有2种使用方法,一种是输入一张静态图片进行检测,另一种是通过摄像头实时检测。

1. 静态图片检测

通过 VKSession.detectBody 接口 输入一张图像,算法检测到图像中的人体,然后通过 VKSession.on 接口 输出获取的人体关键点信息。

示例代码:

const session = wx.createVKSession({
  track: {
    body: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 静态图片检测模式下,每调一次 detectBody 接口就会触发一次 updateAnchors 事件
session.on('updateAnchors', anchors => {
    this.setData({
        anchor2DList: anchors.map(anchor => {
            points: anchor.points, // 关键点坐标
            origin: anchor.origin, // 识别框起始点坐标
            size: anchor.size // 识别框的大小
        }),
    })
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
    session.detectBody({
      frameBuffer, // 图片 ArrayBuffer 数据。待检测图像的像素点数据,每四项表示一个像素点的 RGBA
      width, // 图像宽度
      height, // 图像高度
      scoreThreshold: 0.5, // 评分阈值
      sourceType: 1 //图片来源, 默认为1, 0表示输入图片来自于视频的连续帧
    })
  }
})

2. 通过摄像头实时检测

算法实时检测相机中的人体姿态,通过 VKSession.on 接口 实时输出检测到的人体关键点。

示例代码:

const session = wx.createVKSession({
  track: {
    body: { mode: 1 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 摄像头实时检测模式下,监测到人体时,updateAnchors 事件会连续触发 (每帧触发一次)
session.on('updateAnchors', anchors => {
    this.data.anchor2DList = []
    this.data.anchor2DList = this.data.anchor2DList.concat(anchors.map(anchor => {
        points: anchor.points,
        origin: anchor.origin,
        size: anchor.size
    }))
})

// 当人体从相机中离开时,会触发 removeAnchors 事件
session.on('removeAnchors', () => {
  console.log('removeAnchors')
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
  }
})

3. 开启3D关键点检测

想要开启人体3D关键点检测能力,静态图片模式仅需要在2D调用基础上增加open3d字段,如下

// 静态图片模式调用
session.detectBody({
      ...,           // 同2D调用参数
      open3d: true,  // 开启人体3D关键点检测能力,默认为false
    })

摄像头实时模式则在2D调用基础上增加3D开关更新函数,如下

// 摄像头实时模式调用
session.on('updateAnchors', anchors => {
  this.session.update3DMode({open3d: true})  // 开启人体3D关键点检测能力,默认为false
  ...,  // 同2D调用参数
})

输出说明

点位说明

人体2D关键点为23点定义,如下图所示。

人体3D关键点为SMPL-24点关节定义,如下图所示。

人体检测

人体检测输出字段包括

struct anchor
{
  points,    // 人体2D关键点在图像中的(x,y)坐标
  origin,    // 人体检测框的左上角(x,y)坐标
  size,      // 人体检测框的宽和高(w,h)
  score,     // 人体检测框的置信度
  confidence // 人体关键点的置信度
}

人体3D关键点

开启人体3D关键点检测能力后,可以获取人体2D及3D关键点信息,其中人体3D关键点输出字段包括

struct anchor
{ 
  ...,               // 人体检测2D输出信息
  points3d,          // 人体3D关键点的(x,y,z)3D坐标
  camExtArray,       // 相机外参矩阵,定义为[R, T \\ 0^3 , 1], 使用相机内外参矩阵可将3D点位投影回图像
  camIntArray        // 相机内参矩阵,参考glm::perspective(fov, width / height, near, far);
}

应用场景示例

  1. 人像抠图。
  2. 越界检测。
  3. 人群流量统计。

程序示例

  1. 实时摄像头body检测能力使用参考
  2. 静态图像body检测能力使用参考

Hand检测

VisionKit 从基础库 2.28.0 版本开始提供手部检测能力。从 微信>=8.1.0 版本开始提供人手3D关键点检测,作为手部检测的扩展能力接口。

方法定义

手部检测有2种使用方法,一种是输入一张静态图片进行检测,另一种是通过摄像头实时检测。

1. 静态图片检测

通过 VKSession.detectHand 接口 输入一张图像,算法检测到图像中的手势,然后通过 VKSession.on 接口 输出获取的手势关键点信息。

示例代码:

const session = wx.createVKSession({
  track: {
    hand: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 静态图片检测模式下,每调一次 detectHand 接口就会触发一次 updateAnchors 事件
session.on('updateAnchors', anchors => {
    this.data.anchor2DList = []
    this.setData({
        anchor2DList: anchors.map(anchor => ({
            points: anchor.points, // 关键点坐标
            origin: anchor.origin, // 识别框起始点坐标
            size: anchor.size, // 识别框的大小
            gesture: anchor.gesture // 手势分类
        })),
    }) 
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
    session.detectHand({
      frameBuffer, // 图片 ArrayBuffer 数据。待检测图像的像素点数据,每四项表示一个像素点的 RGBA
      width, // 图像宽度
      height, // 图像高度
      scoreThreshold: 0.5, // 评分阈值
      algoMode: 2 //算法模式:0, 检测模式,输出框和点;1,手势模式,输出框和手势分类;2,同时具备0和1,输出框、点、手势分类
    })
  }
})

2. 通过摄像头实时检测

算法实时检测相机中的手势姿态,通过 VKSession.on 接口 实时输出检测到的手势关键点。

示例代码:

const session = wx.createVKSession({
  track: {
    hand: { mode: 1 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 摄像头实时检测模式下,监测到手势时,updateAnchors 事件会连续触发 (每帧触发一次)
session.on('updateAnchors', anchors => {
    this.data.anchor2DList = []
    this.data.anchor2DList = this.data.anchor2DList.concat(anchors.map(anchor => ({
        points: anchor.points,
        origin: anchor.origin,
        size: anchor.size
    })))
})

// 当手势从相机中离开时,会触发 removeAnchors 事件
session.on('removeAnchors', () => {
  console.log('removeAnchors')
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
  }
})

3. 开启3D关键点检测

想要开启人手3D关键点检测能力,静态图片模式仅需要在2D调用基础上增加open3d字段,如下

// 静态图片模式调用
session.detectHand({
      ...,           // 同2D调用参数
      open3d: true,  // 开启人手3D关键点检测能力,默认为false
    })

摄像头实时模式则在2D调用基础上增加3D开关更新函数,如下

// 摄像头实时模式调用
session.on('updateAnchors', anchors => {
  this.session.update3DMode({open3d: true})  // 开启人手3D关键点检测能力,默认为false
  ...,  // 同2D调用参数
})

输出说明

点位说明

人手2D关键点定义与OpenPose相同,采用21点点位定义,如下图所示。

人手3D关键点采用MANO-16点关节定义,如下图所示。

人手检测

人手检测输出字段包括

struct anchor
{
  points,     // 人手2D关键点在图像中的(x,y)坐标
  origin,     // 人手检测框的左上角(x,y)坐标
  size,       // 人手检测框的宽和高(w,h)
  score,      // 人手检测框的置信度
  confidence, // 人手关键点的置信度
  gesture     // 人手手势类别
}

人手3D关键点

开启人手3D关键点检测能力后,可以获取人手2D及3D关键点信息,其中人手3D关键点输出字段包括

struct anchor
{ 
  ...,               // 人手检测2D输出信息
  points3d,          // 人手3D关键点的(x,y,z)3D坐标
  camExtArray,       // 相机外参矩阵,定义为[R, T \\ 0^3 , 1], 使用相机内外参矩阵可将3D点位投影回图像
  camIntArray        // 相机内参矩阵,参考glm::perspective(fov, width / height, near, far);
}

应用场景示例

  1. 智能家居。
  2. AR互动。
  3. 智能车载。

程序示例

  1. 实时摄像头手部检测能力使用参考
  2. 静态图像手部检测能力使用参考

Shoe 鞋部检测

VisionKit 从基础库 3.2.1 版本 (安卓微信>=8.0.43,iOS微信>=8.0.43) 开始支持。

鞋子检测 能力作为与 其他 VisionKit 能力 平行的能力接口。

该能力一般用于用户进行 AR试鞋 或者 腿部遮挡 等功能的开发。

方法定义

鞋子检测,目前只支持通过 摄像头实时检测

可以通过配置,决定是否每帧获取 用于对鞋子的腿部区域进行蒙版过滤的 腿部遮挡纹理

摄像头实时检测

首先需要创建 VKSession 的配置,然后通过 VKSession.start 启动 VKSession 实例。

运行过程中,算法实时检测相机中的鞋子,通过 VKSession.on 实时输出鞋子矩阵信息(位置旋转缩放)、8个关键点坐标。

最后,实时获取 VKSession 的帧数据 VKFrame,获得 VKCamera。得到 VKCamera.viewMatrixVKCamera.getProjectionMatrix 并结合,鞋子矩阵关键点信息 进行具体渲染。

开启VKSession示例代码:

// VKSession 配置
const session = wx.createVKSession({
    track: {
        shoe: {
            mode: 1 // 1 使用摄像头
        }
    }
})

// 摄像头实时检测模式下,监测到鞋子时,updateAnchors 事件会连续触发 (每帧触发一次)
session.on('updateAnchors', anchors => {
    // 目前版本能识别 1-2 双鞋子,anchors 长度为 0-2
    anchors.forEach(anchor => {
        // shoedirec 鞋子左右,0 为左,1 为右。
        console.log('anchor.shoedirec', anchor.shoedirec)
        // transform 鞋子的矩阵信息(位置旋转缩放),4*4 行主序矩阵,
        console.log('anchor.transform', anchor.transform)
        // points3d 位置,8个关键点坐标
        console.log('anchor.points3d', anchor.points3d)
    })
})

// 摄像头实时检测模式下,当鞋子从相机中丢失时,会不断触发
session.on('removeAnchors', () => {
  console.log('removeAnchors')
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
  }
})

渲染试鞋示例代码:

// 可以理解每一帧都需要执行的行为

// 1. 通过 VKSession 实例的 `getVKFrame` 方法可以获取到帧对象
const frame = this.session.getVKFrame(canvas.width, canvas.height)

// 2. 获取 VKCamera
const VKCamera = frame.camera

// 3. 获取 VKCamera 的 视图矩阵与投影矩阵
const viewMat = VKCamera.viewMatrix;
const projMat = VKCamera.getProjectionMatrix(near, far);

// 4. 结合 updateAnchors 里面返回 anchor 的 transform、points3d 进行具体渲染。(具体可以参考官方示例)

开启腿部遮挡

摄像头实时模式下,想要开启腿部分割能力。

需要保证在 VKSession.start 接口 调用,开启 VKSession 后。 调用 VKSessionupdateMaskMode 更新是否开启腿部分割纹理的返回。然后通过 VKFramegetLegSegmentBuffer 获取具体的腿部遮挡纹理buffer,然后基于 buffer 创建纹理,进行对应的遮挡剔除。

示例代码:

// 1. 开启腿部遮挡纹理获取开关
// VKSession.start 后,可以通过 updateMaskMode 更新是否能够获取腿部遮挡纹理buffer
this.session.updateMaskMode({
    useMask: true // 开启或关闭腿部遮挡纹理buffer (客户端 8.0.43 默认开启获取,可以手动关闭)
});

// 2. 通过 VKSession 实例的 `getVKFrame` 方法可以获取到帧对象
const frame = this.session.getVKFrame(canvas.width, canvas.height)

// 3. 通过帧对象,获取具体腿部分割纹理Buffer(160*160、单通道)
const legSegmentBuffer = frame.getLegSegmentBuffer();

// 4. 基于腿部分割纹理过滤内容(具体可以参考官方案例)

PS.除了算法分割外,可以手动添加Mesh进行遮挡,可以实现类似的遮挡分割效果。具体可以参考官方案例。

输出说明

anchor 信息

struct anchor
{
  transform,  // 鞋子矩阵信息,位置旋转缩放
  points3d,   // 鞋子关键点数组
  shoedirec,  // 鞋子左右脚,0 为左脚,1 为右脚
}

1. 鞋子矩阵 transform

长度为 16 的数组,表示 行主序 的 4*4 矩阵。

2. 鞋子关键点 points3d

长度为 8 的数组,表示 鞋子识别的 8个关键点:

Array<Point>(8) point3d

每个数组元素结构为:

struct Point { x, y, z }

表示在 鞋子矩阵 作用后,每个点的 三维偏移位置

以下为关键点图示与点位解释:

  • 点位0 位于鞋的底部后部,脚后跟处,靠近地面的位置。
  • 点位1 位于鞋子最前面,在竖直方向上大致处于鞋子上表面和鞋子下底面的中间。
  • 点位2 位于鞋的后部,在点位0的上方,位于靠近脚踝的位置。
  • 点位3、4 位于鞋子侧面,其中3点位于左鞋的左侧,右鞋的右侧。4点位于左鞋子的右侧,右鞋的左侧。上图中的3点处于被遮挡的位置。3,4点均紧靠鞋子下底面。
  • 点位5,6 位于鞋子侧面,相对于3,4更靠后,在鞋子下底面偏上一点的位置。
  • 点位7 大致位于鞋舌的中央。

3.腿部分割纹理Buffer

160*160 的 单通道浮点数颜色 ArrayBuffer,数值 0.0 对应非腿部区域,大于 0.0 代表是腿部区域,越靠近 1.0 越接近是腿部区域。

如何基于返回信息摆放模型

首先,可以将添加一个节点同步鞋子矩阵信息。再往该节点添加模型,基于鞋子关键点,设置对应的偏移,然后可以缩放模型适配比例,使模型贴合鞋子关键点,达到目标效果。

程序示例

摄像头实时检测示例

微信小程序示例 的 接口VisionKit视觉能力实时鞋部检测 - 试鞋案例

开源地址:实时鞋部检测-试鞋案例

识别鞋子,并将鞋子模型放置到识别出的区域。默认并支持动态开启与关闭腿部遮挡,以及显示与隐藏对应的鞋子关键点。

案例效果:

OCR检测

VisionKit从基础库 2.27.0版本开始提供OCR能力。

方法定义

OCR检测有2种使用方法,一种是输入一张静态图片进行检测,另一种是通过摄像头实时检测。

1. 静态图片检测

通过 VKSession.runOCR 接口 输入一张图像,算法检测到图像中的文字,然后通过 VKSession.on 接口 输出获取的文字内容。

示例代码:

const session = wx.createVKSession({
  track: {
    OCR: { mode: 2 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 静态图片检测模式下,每调一次 runOCR 接口就会触发一次 updateAnchors 事件
session.on('updateAnchors', anchors => {
  console.log('anchors.text', "".concat(anchors.map(anchor=>anchor.text)))
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
    session.runOCR({
      frameBuffer, // 图片 ArrayBuffer 数据。待检测图像的像素点数据,每四项表示一个像素点的 RGBA
      width, // 图像宽度
      height, // 图像高度
    })
  }
})

2. 通过摄像头实时检测

算法实时检测相机中的文字内容,通过 VKSession.on 接口 实时输出文字。

示例代码:

const session = wx.createVKSession({
  track: {
    OCR: { mode: 1 } // mode: 1 - 使用摄像头;2 - 手动传入图像
  },
})

// 摄像头实时检测模式下,监测到文字时,updateAnchors 事件会连续触发 (每帧触发一次)
session.on('updateAnchors', anchors => {
  console.log('anchors.text',"".concat(anchors.map(anchor=>anchor.text)))
})

// 当文字区域从相机中离开时,会触发 removeAnchors 事件
session.on('removeAnchors', () => {
  console.log('removeAnchors')
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
  }
})

应用场景示例

  1. 文本检测。
  2. 车牌识别。
  3. 证件文本识别。

程序示例

  1. 实时摄像头OCR检测能力使用参考
  2. 静态图像OCR检测能力使用参考

身份证检测

VisionKit 从基础库 3.3.0 版本后开始支持。

身份证检测 能力作为与 其他 VisionKit 能力 平行的能力接口。

该能力,一般用于用户进行 身份证识别 或者 身份证裁剪 等功能的开发。

方法定义

身份证检测,目前只支持通过 视觉模式,即输入一张静态图片进行身份证识别,返回身份证对应信息。

可以通过配置 getAffineImg,决定每次识别是否返回 身份证区域裁剪矩阵

输入身份证图片要求

输入的身份证图片,尽量以 正常的角度拍摄。不同角度带来的 透视效果,会影响识别的 准确度

视觉模式接口

首先需要创建 VKSession 的配置,然后通过 VKSession.start 启动 VKSession 实例。

开启 VKSession,并添加返回对应身份证信息监听事件,示例代码:

// VKSession 配置
const session = wx.createVKSession({
    track: {
        IDCard: {
            mode: 2 // 照片模式
        }
    },
    version: 'v1',
})

// VKSession start
session.start(err => {

  // 静态图片估计模式下,每调一次 detectIDCard 接口就会触发一次 updateAnchors 事件
  session.on('updateAnchors', anchors => {
      // 处理返回的身份证信息
      if (anchors && anchors[0]) {
          // 存在数组,证明存在身份证信息
          const anchor = anchors[0];

          // 识别信息
          const isComplete = anchor.isComplete; // 身份证是否完整
          const label = anchor.label; // 身份证面信息(0 照片面 / 1 国徽面 )
          const orientation = anchor.orientation; // 身份证朝向 (0 朝上 1 朝下 2 朝下 3 朝左)
          const box = anchor.box; // 身份证坐标框点数组 (0 左上点 1 右上点 2 右下点 3 左下点)

          // 裁剪信息,接口 getAffineImg 为 true 时会返回。
          const affineImgWidth = anchor.affineImgWidth;
          const affineImgHeight = anchor.affineImgHeight;
          const affineMat = anchor.affineMat;

          // 存在裁剪信息,可以结合原图获取裁剪后的身份证图片
          if (affineImgWidth && affineImgHeight && affineMat) {
            /*
              * affineMat 3x3仿射变换矩阵,行主序
              *  [0 1 2
              *   3 4 5
              *   6 7 8]
              */
            /*
              * canvas 2d setTransform
              * setTransform(a, b, c, d, e, f)
              *  [a c e
              *   b d f
              *   0 0 1]
              */
             // 可以利用离屏的Canvas2D,结合原图与裁剪矩阵,进行具体的身份证图片裁剪。
          }
      }

  })
  // 图片没有识别到身份证,会触发一次 removeAnchors
  session.on('removeAnchors', anchors => {
      console.log("没有识别到身份证")
  })
});

调用身份证识别,示例代码:


// 调用具体的身份证图片识别接口
session.detectIDCard({
    // 识别身份证图片的 ArrayBuffer,Uint8ClampedArray,RGBA
    // 比如可以通过 canvas(2D)的 context.getImageData 获取
    frameBuffer: imgDataBuffer,
    // 传入识别图片的原始宽度
    width: imgOriginWidth,
    // 传入识别图片的原始高度
    height: imgOriginHeight,
    // 是否获取裁剪图片信息
    getAffineImg: true,
})
// 调用后,识别处理完毕后
// 识别成功会触发 updateAnchors 回调,处理失败会触发 removeAnchors 回调

输出说明

anchor 信息

struct anchor
{
  isComplete,  // 身份证是否完整
  label,       // 身份证面信息(0 照片面 / 1 国徽面 )
  orientation, // 身份证朝向 (0 朝上 1 朝下 2 朝下 3 朝左)
  box,         // 身份证坐标框点数组 (0 左上点 1 右上点 2 右下点 3 左下点)
  /* 身份证裁剪信息
   * getAffineImg 为 true 时返回 */
  affineImgWidth,   // 身份证裁剪宽度
  affineImgHeight,  // 身份证裁剪区域高度
  affineMat,        // 身份证裁剪矩阵
}

身份证坐标框点数组 box

长度为 4 的数组,表示身份证位于原图中,框的坐标点位置。

Array<Point>(8) box

每个数组元素结构为:

struct Point { x, y }

身份证裁剪矩阵 affineMat

长度为 9 的数组,表示行主序的 3×3 仿射变换矩阵。可以结合 Canvas (2D) 以及原图进行具体的身份证图片裁剪。

程序示例

身份证照片识别示例

微信小程序示例的 接口VisionKit 视觉能力照片身份证识别

开源地址:照片身份证识别

深度估计

VisionKit 提供深度估计能力。

深度估计,就是获取图像中场景里的每个点到相机的距离信息,这种距离信息组成的图我们称之为深度图。

方法定义

我们在这里提供了深度估计的两种模式:

视觉模式: (安卓微信>=8.0.37,iOS微信>=8.0.38起) 使用摄像头进行深度估计 。

AR模式: (安卓微信>=8.0.38同时基础库>=2.33.0,iOS微信>=8.0.39同时基础库>=3.0.0) 使用摄像头和IMU进行深度估计,输出由near和far控制的非线性深度图,用于做虚实遮挡,目前支持部分机型,支持机型列表等同于6Dof-水平面AR-V2平面AR接口支持列表

接口类型 精度 机型覆盖率
视觉模式
AR模式

视觉模式接口

深度估计视觉模式接口提供2种使用方法,一种是输入一张静态图片进行深度估计,另一种是通过摄像头进行实时深度估计。

  1. 静态图片估计

通过VKSession.detectDepth接口输入一张图像,然后通过VKSession.on接口监听深度图信息,图中像素的值代表当前的深度值,颜色越黑,代表距离摄像头越近,反之颜色越白,代表距离深度越远。

示例代码:


const session = wx.createVKSession({
  track: {
    depth: {
      mode: 2 // mode: 1 - 使用摄像头;2 - 手动传入图像
    },
  },
  gl: this.gl,
})
// 静态图片估计模式下,每调一次 detectDepth 接口就会触发一次 updateAnchors 事件
session.on('updateAnchors', anchors => {
  anchors.forEach(anchor => {
    console.log('anchor.depthArray', anchor.depthArray) // 深度图 ArrayBuffer 数据
    console.log('anchor.size', anchor.size) // 深度图大小,结果为数组[宽, 高]
  })
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 否则,返回null,表示成功
    session.detectDepth({
      frameBuffer, // 待检测图片的ArrayBuffer 数据。待检测的深度图像RGBA数据, 
      width, // 图像宽度
      height, // 图像高度
    })
  }
})
  1. 通过摄像头实时估计

算法实时输出当前帧的深度图,每一帧像素的值代表当前的深度值,颜色越黑,代表距离摄像头越近,反之颜色越白,代表距离深度越远。

示例代码:

const session = wx.createVKSession({
  track: {
    depth: {
      mode: 1 // mode: 1 - 使用摄像头;2 - 手动传入图像
    },
  },
})

// 需要调用一次 start 以启动
session.start(errno => {
  if (errno) {
    // 如果失败,将返回 errno
  } else {
    // 获取每一帧的信息
    const frame = session.getVKFrame(canvas.width, canvas.height)
    // 获取每帧的深度图信息
    const depthBufferRes = frame.getDepthBuffer();
    const depthBuffer = new Float32Array(depthBufferRes.DepthAddress)
    //创建渲染逻辑, 将数组值传输到一张纹理上,并渲染到屏幕
    render()
  }
})

AR模式接口

详情见水平面AR中的V2+虚实遮挡

实时估计输出说明

1. 效果展示

2. 深度估计关键点

深度实时关键点输出字段包括

struct anchor
{
  DepthAddress, // 深度图ArrayBuffer的地址, 用法如new Float32Array(depthBufferRes.DepthAddress); 
  width,    // 返回深度图的宽
  height,      // 返回深度图的高
}

应用场景示例

  1. 特效场景。
  2. AR游戏以及应用(如下是AR虚实遮挡的例子)。

planev2_deepocc_gif

程序示例

视觉模式:

  1. 实时深度估计能力使用参考
  2. 静态图像深度估计能力使用参考

AR模式:

  1. V2平面+虚实遮挡

demo体验

视觉模式:

  1. 实时深度估计能力,在微信小程序示例中的接口-VisionKit视觉能力-实时深度图检测中体验。
  2. 照片深度估计能力,在微信小程序示例中的接口-VisionKit视觉能力-照片深度图检测中体验。

AR模式:

  1. 在微信小程序示例中的接口-VisionKit视觉能力-水平面AR-v2-虚实遮挡中体验。