MLKitFaceMesh 拓展
检测 468 个面部关键点(带 x/y/z 坐标),用于 AR 贴纸定位、美颜、面部特效。
为什么选它:
- 完全离线。模型随
.aix打包,设备不需要 Google Play 服务,断网也能用。 - 不把 468 个点塞进事件。全序列化有几十 KB,而大多数场景只要某几个区域 —— 所以事件只给摘要,要点时按需调「区域点」(12 个区域任选)或「全部点」。 结果缓存在组件里,检测一次可以反复取不同区域,不用重新识别。
- 可以只要人脸框(
boundingbox模式)——比出网格快得多。
限制:这是 ML Kit 的 beta 功能;要求人脸离镜头较近(约 2 米内)且基本正面。 远景、大角度侧脸检测不到。
与 MLKitFaceDetector 的区别:那个给的是人脸框 + 微笑/睁眼概率 + 头部转角(约 10 项信息); 本拓展给的是 468 个点的几何网格,用来贴图和变形。
- .aix 拓展下载:
快速上手
一、检测并取左眼的点
when 图像选择器1.AfterPicking() {
标签1.Text = "检测中…"
FaceMesh1.DetectFromFile(图像选择器1.Selection)
}
when FaceMesh1.GotFaceMesh(faceCount, pointCount, boundsJson) {
标签1.Text = join("检测到 ", faceCount, " 张脸,", pointCount, " 个点")
标签_眼睛.Text = FaceMesh1.RegionPoints("LEFT_EYE", 1)
}
when FaceMesh1.NoFaceFound(operation) {
标签1.Text = "没检测到人脸,请让脸离镜头近一些、正对镜头"
}
when FaceMesh1.DetectFailed(operation, errorMessage) {
标签1.Text = errorMessage
}
点的 JSON 形状(用「JSON 文本解码」块解析):
[{"index":33,"x":123.4,"y":56.7,"z":-12.3},
{"index":34,"x":126.1,"y":57.2,"z":-12.0}]
x/y 是原图像素坐标,z 是相对深度(越小越靠近镜头)。
二、同一次检测取多个区域(不用重新识别)
when FaceMesh1.GotFaceMesh(faceCount, pointCount, boundsJson) {
标签_左眼.Text = FaceMesh1.RegionPoints("LEFT_EYE", 1)
标签_右眼.Text = FaceMesh1.RegionPoints("RIGHT_EYE", 1)
标签_嘴唇.Text = FaceMesh1.RegionPoints("UPPER_LIP_TOP", 1)
标签_脸部轮廓.Text = FaceMesh1.RegionPoints("FACE_OVAL", 1)
}
三、只要人脸框(快得多)
when Screen1.Initialize() {
FaceMesh1.UseCase = "boundingbox"
}
when FaceMesh1.GotFaceMesh(faceCount, pointCount, boundsJson) {
标签1.Text = boundsJson
}
四、把可用区域做成下拉框
when Screen1.Initialize() {
列表选择器_区域.ElementsFromString = FaceMesh1.AvailableRegions
}
when 列表选择器_区域.AfterPicking() {
标签1.Text = FaceMesh1.RegionPoints(列表选择器_区域.Selection, 1)
}
12 个可用区域
FACE_OVAL(脸廓)、LEFT_EYEBROW_TOP / LEFT_EYEBROW_BOTTOM(左眉上/下沿)、
RIGHT_EYEBROW_TOP / RIGHT_EYEBROW_BOTTOM(右眉上/下沿)、
LEFT_EYE / RIGHT_EYE(左/右眼)、
UPPER_LIP_TOP / UPPER_LIP_BOTTOM(上唇上/下沿)、
LOWER_LIP_TOP / LOWER_LIP_BOTTOM(下唇上/下沿)、NOSE_BRIDGE(鼻梁)。
左右以被拍摄者为准(不是画面左右)—— 自拍时会和直觉相反。
属性
- UseCase
- 检测模式。
mesh(默认)= 输出 468 个网格点;boundingbox= 只输出人脸边界框(快得多,不给点)。 填了认不出的值会回退到mesh。改这个属性会重建检测器,立即生效。 - AvailableRegions
- 只读。可用的区域名,英文逗号分隔。可以直接喂给列表选择框的
ElementsFromString。 - Busy
- 只读。是否正在检测。
事件
- GotFaceMesh(faceCount,pointCount,boundsJson)
- 检测完成(只给摘要)。
pointCount在mesh模式下是 468、boundingbox模式下是 0;boundsJson是第一张脸的边界框。 要拿点请在这个事件里调「区域点」或「全部点」方法 —— 结果已缓存,可反复取不同区域。 - NoFaceFound(operation)
- 图里没检测到人脸。这不是错误 —— 面部网格要求人脸离镜头较近且基本正面。
- DetectFailed(operation,errorMessage)
- 检测失败。
方法
- DetectFromFile(path)
- 检测图片文件。
path可以是素材文件名、设备路径、file://或content://地址。 - DetectFromBase64(base64)
- 检测 Base64 图片。支持带
data:image/...;base64,前缀的写法。 - RegionPoints(regionName,faceIndex)
- 取上一次检测结果里某个区域的点,返回 JSON 数组。
faceIndex从 1 开始。 没有结果或区域名不对时返回[](不会报错)。 - AllPointsJson(faceIndex)
- 取全部 468 个点。⚠️ 数据量大(几十 KB),一般用「区域点」就够了。
- BoundsJson(faceIndex)
- 取某张脸的边界框 JSON。没有结果时返回
{}。
运行环境:AI 伴侣联机需要 Android 11 及以上
本拓展的识别模型放在依赖库自带的 assets 里,AI 伴侣联机调试要把它挂进
AssetManager,用的是 Android 11(API 30)才有的 ResourcesLoader —— 这是系统提供的
唯一公开办法,更低版本没有等价 API。所以:
| 运行方式 | Android 6 ~ 10 | Android 11 及以上 |
|---|---|---|
| 打包 APK | ✅ 正常 | ✅ 正常 |
| AI 伴侣联机 | ❌ 模型加载不了 | ✅ 正常 |
打包 APK 之所以不受限制,是因为模型在编译时就被并进了 APK 的 assets,装到手机上 就是 App 自己的资源,与系统版本无关。伴侣的 APK 是提前编好装在手机上的,运行时没法 往自己已安装的包里加文件,只能靠系统的运行时挂载 API。
低版本设备上想验证功能,直接打包 APK 测即可;要用伴侣边改边调,请换 Android 11+ 的设备。
常见问题
总是触发「没检测到人脸」。
面部网格对距离很敏感 —— 要求人脸离镜头约 2 米内且基本正面。
远景合照、大角度侧脸、严重遮挡都检测不到。先用 MLKitFaceDetector(普通人脸检测)确认图里有脸,
那个的检测范围宽得多。
取点的方法返回 []。
三种可能:① 还没检测成功就调了(要在 GotFaceMesh 事件里调);
② 区域名拼错了(用 可用区域 属性对一下);③ 检测模式 设成了 boundingbox(那个模式不产生点)。
点画到画布上位置不对。
x/y 是原图像素坐标,画布是显示尺寸,要按 画布宽 / 原图宽 换算。
为什么 .aix 有 26 MB?
除了 2.9 MB 的网格模型,还有 21.6 MB 的 mediapipe 推理引擎(4 个 CPU 架构的原生库)。
这是「完全离线、不依赖 Google Play 服务」的代价。
扫码添加客服咨询