自定义模型拓展(两个)
基础模型只有粗类别 —— 图像标注是 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 模型,且带元数据(含标签)。最省事的两条路:
- Google Teachable Machine(teachablemachine.withgoogle.com)—— 浏览器里上传几十张图就能训练分类模型,导出时选 TensorFlow Lite → 模型转换类型 Floating point。 零代码,适合教学。
- AutoML Vision Edge / TensorFlow Lite Model Maker —— 需要一点代码,能训分类和检测模型。
导出的 .tflite 文件上传到 App Inventor 项目的「素材」里,然后把文件名填进 模型文件 属性。
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 图片。
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 服务」的代价。
扫码添加客服咨询