MLKitObjectDetector 拓展
找出图片里有哪些物体,并给出每个物体的位置矩形框。
为什么选它:
- 完全离线。模型随
.aix打包,设备不需要 Google Play 服务,断网也能用。 - 两种事件,各取所需:汇总事件
GotObjects一次给全(含 JSON), 逐个事件GotObject带序号和框坐标 —— 初学者直接在逐个事件里画框最省事。 - 可选只找最显眼的一个(更快)还是找出多个;可选是否要粗分类。
- 不用先”初始化”,检测器按需创建、复用。
与 MLKitImageLabeler 的区别:图像标注只告诉你「图里有花」, 本拓展还告诉你「花在 (x, y) 起、宽 w 高 h 的框里」,并能一次框出多个物体。
- .aix 拓展下载:
cn.fun123.MLKit.ObjectDetector.aix
快速上手
一、检测并逐个画框
设计器里放一个 MLKitObjectDetector、一个「图像选择器」、一个画布(用来画框)。
global scale = 1
when 图像选择器1.AfterPicking() {
标签1.Text = "检测中…"
ObjectDetector1.DetectFromFile(图像选择器1.Selection)
}
when ObjectDetector1.GotObjects(count, imageWidth, imageHeight, resultJson) {
标签1.Text = join("找到 ", count, " 个物体")
画布1.BackgroundImage = 图像选择器1.Selection
scale = 画布1.Width / imageWidth
}
when ObjectDetector1.GotObject(index, x, y, width, height, label, confidence, trackingId) {
画布1.PaintColor = -65536
画布1.DrawLine(x * scale, y * scale, (x + width) * scale, y * scale)
画布1.DrawLine((x + width) * scale, y * scale, (x + width) * scale, (y + height) * scale)
画布1.DrawLine((x + width) * scale, (y + height) * scale, x * scale, (y + height) * scale)
画布1.DrawLine(x * scale, (y + height) * scale, x * scale, y * scale)
画布1.DrawText(label, x * scale, y * scale)
}
坐标要换算:事件给的是原图像素坐标,画到画布上要乘以
画布宽 / 原图宽。 这就是汇总事件里给imageWidth/imageHeight的用途。
二、只要最显眼的那一个(更快)
when Screen1.Initialize() {
ObjectDetector1.MultipleObjects = false
ObjectDetector1.Classification = true
}
三、只要位置不要分类(最快)
when Screen1.Initialize() {
ObjectDetector1.Classification = false
}
四、拿完整结果自己处理
when ObjectDetector1.GotObjects(count, imageWidth, imageHeight, resultJson) {
标签_原始结果.Text = resultJson
}
resultJson 的形状(用「JSON 文本解码」块解析):
[{"bounds":{"left":120,"top":80,"right":420,"bottom":560,"width":300,"height":480},
"trackingId":-1,
"labels":[{"label":"Fashion good","confidence":0.78,"index":0}]}]
五、什么都没检测到时给个提示
when ObjectDetector1.NoObjectFound(operation) {
标签1.Text = "没检测到物体。目标检测适合画面里有明确主体的照片"
}
属性
- MultipleObjects
- 是否检测多个物体。 「真」(默认)= 找出画面里最多 5 个物体;「假」= 只找最显眼的那一个(更快)。 改这个属性会重建检测器,立即生效。
- Classification
- 是否同时给出粗分类。 「真」(默认)= 每个物体附带类别名和置信度;「假」= 只给位置框(更快)。 注意基础模型只有 5 个大类(时尚商品 / 食物 / 家居用品 / 地点 / 植物), 要精细分类请用自定义模型版拓展。
- Busy
- 只读。是否正在检测。检测期间再次调用会触发
DetectFailed。
事件
- GotObjects(count,imageWidth,imageHeight,resultJson)
- 检测完成的汇总,在逐个事件之前触发。
imageWidth/imageHeight是原图尺寸 —— 画框换算坐标时必须用它。 - GotObject(index,x,y,width,height,label,confidence,trackingId)
- 每检测到一个物体触发一次,方便逐个画框。
index— 从 1 开始的序号。x/y— 框的左上角;width/height— 框的宽高。单位是原图像素。label/confidence— 粗分类结果(是否分类为「假」时label为空串)。trackingId— 跨帧跟踪编号,单张图片检测时固定为 -1。
- NoObjectFound(operation)
- 图里没检测到物体。这不是错误 —— 目标检测适合画面里有明确主体的照片, 纯风景 / 纯文字图常常检测不到。
- DetectFailed(operation,errorMessage)
- 检测失败。
operation是出错的方法名。
方法
- DetectFromFile(path)
- 检测图片文件。
path可以是素材文件名、设备路径、file://或content://地址。 - DetectFromBase64(base64)
- 检测 Base64 图片。支持纯 Base64,也支持带
data:image/...;base64,前缀的写法。
运行环境: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+ 的设备。
常见问题
画的框位置全错 / 偏得很远。
坐标没换算。事件给的是原图像素坐标,而画布是按显示尺寸的。
用汇总事件里的 imageWidth 算出比例:比例 = 画布宽 / imageWidth,然后所有坐标乘以它(见示例一)。
分类结果只有”时尚商品”“食物”这种大类。 基础模型就只有 5 个大类,这是能力边界,不是 bug。要认具体品类请用自定义 TFLite 模型版拓展。
trackingId 一直是 -1。
跟踪编号只在摄像头连续帧模式下才有意义。本拓展是单张图片检测,所以固定 -1。
能检测摄像头实时画面吗?
本拓展做的是单张图片检测。实时检测需要摄像头预览 + 逐帧处理 + 叠加画框,
可以参考本仓库 MLKit.CodeScanner 拓展里的实时预览实现思路,但本拓展当前不提供该能力。
为什么 .aix 有 23 MB?
除了 1.8 MB 的检测模型,还有 18.7 MB 的推理引擎(4 个 CPU 架构的原生库),
这是「完全离线、不依赖 Google Play 服务」的代价。
扫码添加客服咨询