MLKitCustomLabeler / MLKitCustomObjectDetector 拓展:用自己的 TFLite 模型

« 返回首页

自定义模型拓展(两个)

基础模型只有粗类别 —— 图像标注是 400 个通用类, 目标检测只有 5 个大类。想认具体品类(花的品种、菜名、 零件型号、垃圾分类……)就要用自己训练的模型。这两个拓展就是干这个的:

拓展 能力 体积
MLKitCustomLabeler 用你的 TFLite 模型做图像分类(这张图是什么) 21.2 MB
MLKitCustomObjectDetector 用你的 TFLite 模型做目标检测(东西在哪 + 是什么) 22.2 MB

共同特点:

  • 完全离线,设备不需要 Google Play 服务。
  • 模型来源不用额外设属性 —— 填的字符串含 / 就当设备绝对路径,否则当项目素材文件名。 你不用先搞懂「素材还是路径」这种实现细节。
  • 标签文字来自模型自带的元数据,所以中文模型直接就输出中文。

  • .aix 拓展下载:

cn.fun123.MLKit.CustomLabeler.aix  |  cn.fun123.MLKit.CustomObjectDetector.aix


模型从哪来

需要 TFLite 模型,且带元数据(含标签)。最省事的两条路:

  1. Google Teachable Machine(teachablemachine.withgoogle.com)—— 浏览器里上传几十张图就能训练分类模型,导出时选 TensorFlow Lite → 模型转换类型 Floating point。 零代码,适合教学。
  2. AutoML Vision Edge / TensorFlow Lite Model Maker —— 需要一点代码,能训分类和检测模型。

导出的 .tflite 文件上传到 App Inventor 项目的「素材」里,然后把文件名填进 模型文件 属性。


logo MLKitCustomLabeler:自定义图像分类

快速上手

when Screen1.Initialize() {
  CustomLabeler1.ModelFile = "flowers.tflite"
  CustomLabeler1.ConfidenceThreshold = 0.6
  CustomLabeler1.MaxResultCount = 3
}
when 图像选择器1.AfterPicking() {
  标签1.Text = "识别中…"
  CustomLabeler1.LabelFromFile(图像选择器1.Selection)
}
when CustomLabeler1.GotLabels(topLabel, topConfidence, labels, resultJson) {
  标签1.Text = join(topLabel, "(", round(topConfidence * 100), "%)")
  列表显示框1.Elements = labels
}
when CustomLabeler1.NoLabelFound(operation) {
  标签1.Text = "没有结果超过置信度阈值,试试调低阈值"
}
when CustomLabeler1.LabelFailed(operation, errorMessage) {
  标签1.Text = errorMessage
}

resultJson 形状:

[{"label":"玫瑰","confidence":0.93,"index":0},
 {"label":"月季","confidence":0.41,"index":3}]

属性

ModelFile
TFLite 模型文件。填素材文件名(如 flowers.tflite)或设备绝对路径(含 / 即视为路径)。 没设就调用会立刻报错并提示你设这个属性。
ConfidenceThreshold
置信度阈值,0~1,默认 0.5。低于这个值的结果不返回。
MaxResultCount
最多返回几个结果,默认 5,至少 1。
Busy
只读。是否正在识别。

事件与方法

GotLabels(topLabel,topConfidence,labels,resultJson)
识别出结果。topLabel/topConfidence 是最可能的那个;labels 是全部标签列表。
NoLabelFound(operation)
没有结果超过置信度阈值。不是错误,可调低阈值。
LabelFailed(operation,errorMessage)
失败。常见原因:模型文件没设或不存在、不是 TFLite 分类模型、模型缺标签元数据。
LabelFromFile(path)
识别图片文件。
LabelFromBase64(base64)
识别 Base64 图片。

logo MLKitCustomObjectDetector:自定义目标检测

用法与基础版目标检测完全一致(同样的事件、同样的坐标换算), 只是多一个 模型文件 属性、分类结果来自你的模型。

快速上手

global scale = 1

when Screen1.Initialize() {
  CustomDetector1.ModelFile = "parts.tflite"
}
when 图像选择器1.AfterPicking() {
  CustomDetector1.DetectFromFile(图像选择器1.Selection)
}
when CustomDetector1.GotObjects(count, imageWidth, imageHeight, resultJson) {
  标签1.Text = join("找到 ", count, " 个")
  画布1.BackgroundImage = 图像选择器1.Selection
  scale = 画布1.Width / imageWidth
}
when CustomDetector1.GotObject(index, x, y, width, height, label, confidence, trackingId) {
  画布1.PaintColor = -65536
  画布1.DrawLine(x * scale, y * scale, (x + width) * scale, y * scale)
  画布1.DrawText(label, x * scale, y * scale)
}
when CustomDetector1.DetectFailed(operation, errorMessage) {
  标签1.Text = errorMessage
}

坐标是原图像素,画到画布要乘 画布宽 / imageWidth —— 和基础版一样。

属性

ModelFile
TFLite 模型文件,规则同上(含 / 当路径,否则当素材名)。没设就调用会立刻报错。
MultipleObjects
是否检测多个物体,默认「真」。
Classification
是否给出分类,默认「真」。分类标签来自你模型自带的元数据。
Busy
只读。是否正在检测。

事件与方法

事件和方法与基础版目标检测完全相同: GotObjects / GotObject / NoObjectFound / DetectFailed、 DetectFromFile / DetectFromBase64。字段含义请看那一页。


运行环境:AI 伴侣联机需要 Android 11 及以上

自定义目标检测(MLKitCustomObjectDetector)用到的目标检测引擎,其模型放在依赖库自带的 assets 里,AI 伴侣联机调试要把它挂进 AssetManager,用的是 Android 11(API 30)才有的 ResourcesLoader —— 这是系统提供的 唯一公开办法,更低版本没有等价 API。所以:

运行方式 Android 6 ~ 10 Android 11 及以上
打包 APK ✅ 正常 ✅ 正常
AI 伴侣联机 ❌ 模型加载不了 ✅ 正常

打包 APK 之所以不受限制,是因为模型在编译时就被并进了 APK 的 assets,装到手机上 就是 App 自己的资源,与系统版本无关。伴侣的 APK 是提前编好装在手机上的,运行时没法 往自己已安装的包里加文件,只能靠系统的运行时挂载 API。

(自定义图像分类 MLKitCustomLabeler 不受此限制。)

低版本设备上想验证功能,直接打包 APK 测即可;要用伴侣边改边调,请换 Android 11+ 的设备。

常见问题

提示「还没有设置模型文件属性」。 按提示设 模型文件。注意这个检查是前置的 —— 没设模型时不会去申请权限和读图片, 所以你会立刻收到这条提示,而不是等一圈才失败。

设了模型但还是失败。 按可能性排查:① 文件名拼错,或忘了把 .tflite 上传到项目素材; ② 模型不是 TFLite 格式(.pb、.h5、.onnx 都不行,要先转换); ③ 模型没有元数据 —— ML Kit 要求模型内嵌标签信息,Teachable Machine 导出的自带, 自己训练的可能要用 TFLite Metadata Writer 补上; ④ 分类模型用到了检测拓展上(或反过来)—— 两者的模型不通用。

能用 Teachable Machine 导出的模型吗? 可以。导出时选 TensorFlow Lite → Floating point,把 .tflite 传进项目素材即可。 它导出的包里还有个 labels.txt,本拓展不需要它(标签读的是模型内嵌元数据)。

识别结果全是英文/乱码标签。 标签来自模型元数据。用中文标签训练导出的模型,这里就直接是中文。

为什么 .aix 有 20MB+? 模型本身很小(几百 KB),大头是 18.7 MB 的推理引擎(4 个 CPU 架构的原生库)。 这是「完全离线、不依赖 Google Play 服务」的代价。

文档反馈