yolo YOLO 检测
约 1476 字大约 5 分钟
yolo YOLO 检测
yolo 是 ScriptX 里的目标检测模块,当前公开的是一套兼容旧插件写法的 NCNN YOLOv8 接口。它适合做:
- 截图后找人脸、按钮、图标、目标框
- 先检测目标区域,再交给点击、OCR、模板匹配去做二次确认
- 用你自己准备的
.param/.bin外部模型跑检测
先记住这 9 条
- 全局对象名是
yolo,兼容别名是$yolo。 yolo不是自动带模型的,必须先ncnn_loadYolov8(...)。- 当前公开方法名就是历史兼容风格的
ncnn_loadYolov8/ncnn_detect/ncnn_unloadYolov8。 ncnn_loadYolov8(...)的第 5 个参数源码里就叫decript,不是decrypt,文档这里按真实 API 写。classNames必须是非空字符串列表。ncnn_detect(...)返回的是两项数组:[检测结果列表, 耗时毫秒]。- 每条检测结果里的
confidence是字符串,不是数字。 - 加密模型模式走的是 AES-CBC,
key必须是 16 / 24 / 32 字节,iv必须是 16 字节。 close()只是ncnn_unloadYolov8()的别名。
yolo.ncnn_loadYolov8(paramPath, modelPath, classNames, useGPU, decript, key, iv)
加载一套 YOLOv8 NCNN 模型。
yolo.ncnn_loadYolov8(
"/sdcard/models/yolo/model.param",
"/sdcard/models/yolo/model.bin",
["person", "cat", "dog"],
false,
false,
"",
""
);
参数
| 参数 | 类型 | 可填值 | 说明 |
|---|---|---|---|
paramPath | string | 非空路径 | NCNN .param 文件路径 |
modelPath | string | 非空路径 | NCNN .bin 文件路径 |
classNames | string[] | 非空列表 | 类别名列表,索引要和模型输出标签一致 |
useGPU | boolean | true / false | 是否尝试走 GPU |
decript | boolean | true / false | 是否先把模型按 AES-CBC 解密后再加载 |
key | string | 任意字符串 | decript=true 时作为 AES key;否则会被忽略 |
iv | string | 任意字符串 | decript=true 时作为 AES-CBC iv;否则会被忽略 |
返回值
boolean
成功时返回 true。
模型文件要求
paramPath和modelPath都必须可读classNames不能为空- 底层 Native 会话必须创建成功,否则会直接报错
useGPU 怎么理解
这里只是“把是否用 GPU 的意图传给底层 NCNN 会话”。
是否真的能跑 GPU,还要看:
- 设备本身
- 这份 NCNN 构建
- 底层 YOLO Native 初始化是否成功
如果 GPU 模式底层起不来,会在加载阶段失败,不会悄悄回退成 CPU。
decript 怎么理解
这是历史兼容命名,真实公开参数名就是:
decript
不是:
decrypt
如果你传对象参数自己封装这套调用,也要记得文档和代码都按 decript 来。
加密模型模式的要求
只有当 decript = true 时,key 和 iv 才会真的参与工作。
要求如下:
| 参数 | 要求 |
|---|---|
key | UTF-8 字节数必须是 16 / 24 / 32 |
iv | UTF-8 字节数必须正好是 16 |
底层流程是:
- 把加密的
.param/.bin解密到私有缓存目录 - 用解密后的临时文件创建 NCNN 会话
- 无论成功失败,临时文件最后都会删掉
示例:普通未加密模型
yolo.ncnn_loadYolov8(
"/sdcard/models/yolo/model.param",
"/sdcard/models/yolo/model.bin",
["person", "button", "avatar"],
false,
false,
"",
""
);
示例:AES-CBC 加密模型
yolo.ncnn_loadYolov8(
"/sdcard/models/yolo/model.param.enc",
"/sdcard/models/yolo/model.bin.enc",
["person", "button", "avatar"],
false,
true,
"1234567890abcdef",
"fedcba0987654321"
);
yolo.ncnn_detect(image, target_size, prob_threshold)
对一张图做目标检测。
const result = yolo.ncnn_detect(image, 640, 0.35);
参数
| 参数 | 类型 | 可填值 | 说明 |
|---|---|---|---|
image | Image / Bitmap / 可解析图片值 | ScriptX 当前支持的图片输入类型 | 待检测图片 |
target_size | number | > 0 的整数 | 送入 YOLO 的目标尺寸 |
prob_threshold | number | 0..1 | 置信度阈值 |
返回值
[detections, durationMs]
也就是一个长度为 2 的数组:
- 第 1 项:检测结果数组
- 第 2 项:耗时,单位毫秒
检测结果项字段
| 字段 | 类型 | 说明 |
|---|---|---|
class | number | 模型输出的类别索引 |
className | string | 由 classNames 映射出的类别名 |
region | number[] | [x1, y1, x2, y2] |
confidence | string | 置信度,保留两位小数字符串 |
调用前的硬前提
必须先成功执行过:
yolo.ncnn_loadYolov8(...);
否则会直接报:
Call yolo.ncnn_loadYolov8 before yolo.ncnn_detect
target_size 怎么选
这不是“必须等于原图尺寸”的意思,而是送进模型前使用的目标边长。
常见选择:
| 值 | 适合场景 |
|---|---|
320 | 小模型、追求速度 |
640 | 最常见的中间值 |
960 或更大 | 目标很小、想提高细节,但耗时会增加 |
prob_threshold 怎么理解
| 值 | 常见效果 |
|---|---|
0.2 | 容易出框,但误检也更多 |
0.35 | 比较常见的折中 |
0.5 以上 | 更严格,漏检概率也会更高 |
一个很关键的细节
返回结果里的 confidence 不是数字,而是字符串。
也就是说:
const result = yolo.ncnn_detect(image, 640, 0.35);
const detections = result[0];
log(typeof detections[0].confidence); // string
如果你后面还要自己做数值比较,记得手动转一下:
parseFloat(detections[0].confidence)
示例:做一次整图检测
const image = images.captureScreen();
try {
const result = yolo.ncnn_detect(image, 640, 0.35);
const detections = result[0];
const durationMs = result[1];
log(`duration=${durationMs}ms`);
log(JSON.stringify(detections, null, 2));
} finally {
image.recycle();
}
示例:找到第一个 person
const image = images.captureScreen();
try {
const result = yolo.ncnn_detect(image, 640, 0.35);
const detections = result[0];
const person = detections.find(function (item) {
return item.className == "person";
});
if (person) {
log(`person=${JSON.stringify(person)}`);
}
} finally {
image.recycle();
}
yolo.ncnn_unloadYolov8() / yolo.close()
卸载当前 YOLO 模型。
返回值
boolean
| 返回值 | 含义 |
|---|---|
true | 当前确实有模型,并且已经释放 |
false | 当前本来就没有加载模型 |
什么时候应该主动卸载
- 后面不会再跑目标检测
- 准备换另一套 YOLO 模型
- 想把 Native 资源尽早释放掉
示例
yolo.ncnn_unloadYolov8();
yolo.isLoaded()
判断当前是否已经有可用的 YOLO 会话。
返回值
boolean
示例
if (!yolo.isLoaded()) {
throw new Error("YOLO 模型还没加载");
}
yolo.api
yolo 自己的别名引用。
类型
object
示例
const api = yolo.api;
log(api === yolo);
一段完整的新手示例
这个例子演示的是:先加载 YOLO 模型,再对截图做检测,然后拿到第一个 button 目标中心点去点击。
yolo.ncnn_loadYolov8(
"/sdcard/models/yolo/model.param",
"/sdcard/models/yolo/model.bin",
["button", "avatar", "person"],
false,
false,
"",
""
);
const image = images.captureScreen();
try {
const result = yolo.ncnn_detect(image, 640, 0.35);
const detections = result[0];
const button = detections.find(function (item) {
return item.className == "button";
});
if (button) {
const region = button.region;
const centerX = Math.floor((region[0] + region[2]) / 2);
const centerY = Math.floor((region[1] + region[3]) / 2);
click(centerX, centerY);
}
} finally {
image.recycle();
yolo.close();
}
