YOLO 推理结果
更新: 2026/3/2 字数: 0 字 时长: 0 分钟
YOLOResults 类是 YOLO 推理的核心返回对象,封装了所有推理结果及其相关操作方法。它支持目标检测、实例分割、图像分类、姿态估计和旋转框检测等多种任务,并提供数据转换、可视化、文件导出等丰富功能。
- YOLOResults 核心结果类
- YOLOObject 单个推理对象
- Boxes 边界框结果
- Masks 分割掩码结果
- Keypoints 关键点姿态结果
- OBB 旋转框结果
- Probs 分类概率结果
- DataFrame 结果数据帧
- Summary 结果摘要对象
YOLOResults
YOLOResults, YOLO推理的结果集合, 通过Yolo.predict()方法返回的对象。 YOLOResults"继承"于数组,实际上是一个YOLOObject的数组,因此可以使用数组的函数和属性,例如使用size()方法获取YOLOResults的大小,使用forEach函数来遍历YOLOResults。 例如,采用forEach遍历屏幕上所有的文本控件并打印出文本内容的代码为:
var yoloResults = yolo.predict(image);
yoloResults.forEach(function(yoloObject){
console.log("类别:", yoloObject.cls, "置信度:", yoloObject.conf);
});例如,使用 for 循环来遍历结果并打印内容的示例代码
var yoloResults = yolo.predict(image);
for (var i = 0; i < yoloResults.size(); i++) {
var yoloObject = yoloResults.get(i);
console.log("类别:", yoloObject.cls, "置信度:", yoloObject.conf);
}YOLOResults.path
path{string}
图像文件路径或标识符
YOLOResults.origShape
origShape{number[]}
原始图像尺寸数组 [height, width]
YOLOResults.names
names{string[]}
类别名称数组
YOLOResults.speed
speed{Speed}
推理速度统计信息
YOLOResults.isEmpty()
- 返回 {boolean}
检查结果是否为空(无检测目标)
var yoloResults = yolo.predict(image);
if (yoloResults.isEmpty()) {
console.log("未检测到任何目标");
}YOLOResults.size()
- 返回 {number}
返回检测目标数量
console.log("检测到 " + yoloResults.size() + " 个目标");YOLOResults.get(index)
index{number} 目标索引- 返回 {YOLOObject}
获取指定索引的目标对象。请确保索引在 [0, yoloResults.size()-1] 范围内。
for (var i = 0; i < yoloResults.size(); i++) {
var obj = yoloResults.get(i);
console.log("类别:", obj.cls, "置信度:", obj.conf);
}⚠️ 若索引越界,会抛出异常。建议循环使用
size()控制范围。
YOLOResults.iterator()
- 返回 {Iterator<YOLOObject>}
返回迭代器,支持 for-each 遍历
for (var obj of yoloResults) {
console.log("类别:", obj.cls, "置信度:", obj.conf);
}YOLOResults.getYoloObjects()
- 返回 {YOLOObject[]}
返回原始推理目标对象数组(可能为空数组,如果推理失败则数组长度为 0),用于一次性获取所有目标对象
var yoloObjects = yoloResults.getYoloObjects();
for (var i = 0; i < yoloObjects.length; i++) {
var obj = yoloObjects[i];
console.log("类别:", obj.cls, "置信度:", obj.conf);
}YOLOResults.isSuccess()
- 返回 {boolean}
true→ 推理成功(可能未检测到任何目标)false→ 推理失败(模型加载失败或传入参数异常)
判断 YOLO 推理是否成功执行
⚠️ 此方法主要用于调试和异常检测。熟悉 YOLO API 后,可直接使用 YOLOResults.getYoloObjects() 遍历结果,无需每次判断。
if (!yoloResults.isSuccess()) {
console.error("推理异常,请检查模型或参数");
}💡 说明:
getYoloObjects()永远返回数组,不会返回null,避免 JS 端多余的 null 判断- 遍历时可直接用
for-of或数组索引 isSuccess()提供显式推理状态判断
YOLOResults.summary([options])
options{object} 配置,可选normalize{boolean} 是否归一化,默认falsedecimals{number} 小数位数,默认5
- 返回 {Summary[]}
获取摘要对象数组
var summaries = yoloResults.summary({
normalize: true,
decimals: 3
});
// 遍历摘要信息
for (var i = 0; i < summaries.length; i++) {
var summary = summaries[i];
console.log("目标: " + summary.name + " (置信度: " + summary.confidence + ")");
if (summary.box) {
console.log("边界框: (" + summary.box.x1 + ", " + summary.box.y1 + ") - (" + summary.box.x2 + ", " + summary.box.y2 + ")");
}
}YOLOResults.boxes()
- 返回 {Boxes | null}
获取边界框检测结果(目标检测任务)非目标检测、实例分割、姿态估计任务时返回 null。
var boxes = yoloResults.boxes();
if (boxes) {
var xyxy = boxes.xyxy(); // 获取所有框的坐标,格式 [[x1, y1, x2, y2], ...]
var classes = boxes.cls(); // 获取所有类别ID,格式 [0, 1, 0, ...]
var confidences = boxes.conf(); // 获取所有置信度,格式 [0.87, 0.92, ...]
for (var i = 0; i < xyxy.length; i++) {
var box = xyxy[i];
console.log(
"框 #" +
i +
": [" +
box[0] +
", " +
box[1] +
", " +
box[2] +
", " +
box[3] +
"]" +
" 类别: " +
classes[i] +
" 置信度: " +
confidences[i]
);
}
} else {
console.error("非目标检测、实例分割、姿态估计任务");
}YOLOResults.masks()
- 返回 {Masks | null}
获取分割掩码结果(实例分割任务)。非实例分割任务时返回 null
var masks = yoloResults.masks();
if (masks) {
var xy = masks.xy(); // 获取原始坐标,格式 [[[x1, y1], [x2, y2], ...], ...]
var xyn = masks.xyn(); // 获取归一化坐标,格式 [[[x1, y1], [x2, y2], ...], ...]
for (var i = 0; i < xy.length; i++) {
console.log("掩码 #" + i + ":");
console.log("原始坐标:\n", JSON.stringify(xy[i], null, 4)); // 打印原始像素坐标
console.log("归一化坐标:\n", JSON.stringify(xyn[i], null, 4)); // 打印归一化坐标
}
} else {
console.error("非实例分割任务");
}YOLOResults.keypoints()
- 返回 {Keypoints | null}
获取关键点检测结果(姿态估计任务)。非姿态估计任务时返回 null。
var keypoints = yoloResults.keypoints();
if (keypoints) {
var xy = keypoints.xy(); // [[ [x,y], ... ], ...]
var conf = keypoints.conf(); // [[0.9, 0.85, ...], ...]
for (var i = 0; i < xy.length; i++) {
// 遍历每个目标
console.log("目标 #" + i + " 关键点信息:");
for (var j = 0; j < xy[i].length; j++) {
// 遍历该目标的关键点
console.log(" 关键点 #" + j + ": [" + xy[i][j][0] + ", " + xy[i][j][1] + "]" + " 置信度: " + conf[i][j]);
}
}
} else {
console.error("非姿态估计任务");
}YOLOResults.obb()
- 返回 {OBB | null}
获取旋转框检测结果(旋转框检测任务)。非旋转框检测任务时返回 null
var obb = yoloResults.obb();
if (obb) {
var xywhr = obb.xywhr(); // 获取旋转框中心点、宽高和旋转弧度,格式 [[x, y, w, h, r], ...]
var corners = obb.xyxyxyxy(); // 获取四个角点坐标,顺序: 右下 -> 右上 -> 左上 -> 左下,格式 [[ [x1,y1], [x2,y2], [x3,y3], [x4,y4] ], ...]
for (var i = 0; i < xywhr.length; i++) {
var radians = xywhr[i][4];
// 弧度 → 角度
var deg = (radians * 180) / Math.PI;
console.log(
"旋转框 #" +
i +
": " +
"中心点=(" +
xywhr[i][0] +
", " +
xywhr[i][1] +
"), " +
"宽=" +
xywhr[i][2] +
", " +
"高=" +
xywhr[i][3] +
", " +
"弧度=" +
radians +
", " +
"角度=" +
deg.toFixed(2) +
"°"
);
var c = corners[i];
console.log("四角坐标 (右下 → 右上 → 左上 → 左下):");
console.log(" 右下: (" + c[0][0] + ", " + c[0][1] + ")");
console.log(" 右上: (" + c[1][0] + ", " + c[1][1] + ")");
console.log(" 左上: (" + c[2][0] + ", " + c[2][1] + ")");
console.log(" 左下: (" + c[3][0] + ", " + c[3][1] + ")");
console.log("--------------------------------------------------");
}
} else {
console.error("非旋转框检测任务");
}YOLOResults.probs()
- 返回 {Probs | null}
获取分类概率结果(图像分类任务)。非图像分类任务时返回 null。
var probs = yoloResults.probs();
if (probs) {
var top1 = probs.top1(); // 获取 Top1 类别 ID
var top1name = probs.top1name(); // 获取 Top1 类别名称
var top1conf = probs.top1conf(); // 获取 Top1 置信度
console.log("分类结果:", top1name, "置信度:", top1conf);
} else {
console.error("当前任务不是分类任务,无分类结果");
}YOLOResults.plot([options])
options{object}(可选)绘图配置lineWidth{number} 边框线宽fontSize{number} 字体大小kptRadius{number} 关键点半径showBoxes{boolean} 是否显示边界框showLabels{boolean} 是否显示标签showConf{boolean} 是否显示置信度showMasks{boolean} 是否显示掩码showKptLine{boolean} 是否显示关键点连线classPalette{float[][]} 类别调色板posePalette{float[][]} 姿态调色板skeleton{int[][]} 骨架连接limbColor{int[]} 骨骼颜色kptColor{int[]} 关键点颜色save{boolean} 是否保存图像fileName{string} 保存的文件名
- 返回 {Image | null}
绘制检测结果并返回图像包装器
// 简单绘制
var img = yoloResults.plot();// 带配置绘制
var img = yoloResults.plot({
lineWidth: 10,
fontSize: 28,
showLabels: true,
showConf: false,
save: true,
fileName: "plot.png",
});YOLOResults.show()
- 返回 {FloatImage}
显示检测结果(悬浮窗显示)
var floatImage = yoloResults.show();
floatImage.setTitle("YOLO 推理");
floatImage.setPosition(100, 100);
floatImage.setSize(device.width * 0.8, device.height * 0.8);
sleep(2000);
floatImage.close();YOLOResults.save([path])
path{string}(可选)保存路径- 返回 {boolean}
保存检测结果图像
保存到默认路径
yoloResults.save();保存到指定路径
yoloResults.save("/sdcard/output/detection.png");YOLOResults.orig()
var origImg = yoloResults.orig();YOLOResults.recycleOrig()
回收检测结果对应的原始图像资源,释放内存占用
注意
- 由
images.captureScreen()截屏获取的 Image 对象为自动回收资源,禁止调用此方法,否则会触发运行时错误 - 非截屏场景的自定义图像资源,建议在使用完毕后及时调用此方法释放,避免内存泄漏
yoloResults.recycleOrig();YOLOResults.recycle()
回收检测结果图像资源(由 YOLO 框架创建的绘制图),释放内存占用
使用要求: 当满足以下任一条件时,会生成绘制图Image对象资源,使用完毕后必须调用此方法回收,避免内存泄漏:
- 推理选项中设置
show: true或save: true - 主动调用
YOLOResults.plot()生成绘制图 - 主动调用
YOLOResults.show()显示绘制图 - 主动调用
YOLOResults.save([path])保存检测结果图
yoloResults.recycle();YOLOResults.recyclePlot()
回收检测结果图像资源,释放内存占用,和YOLOResults.recycle()一样
YOLOResults.recycleAll()
回收原图 + 绘制图的图像资源,释放内存占用,是多场景下的快捷回收方法。
相当于YOLOResults.recycleOrig()+YOLOResults.recyclePlot()
适用场景: 本地/网络图片推理、视频帧推理、相机帧推理场景,可一次性完成所有图像资源回收,简化代码编写
yoloResults.recycleAll();提示
系统截屏 images.captureScreen() 推理场景禁止调用YOLOResults.recycleAll()方法,否则会因回收系统托管的原图触发错误,此类场景仅需调用 YOLOResults.recycle() 即可
YOLOResults.verbose()
- 返回 {string}
获取简洁的结果摘要字符串
console.log(yoloResults.verbose());
// 输出: "4 persons, 1 car, 2 traffic lights"YOLOResults.verbosePredict()
- 返回 {string}
获取详细预测结果字符串
console.log(yoloResults.verbosePredict());
// 输出: "640x480 4 persons, 1 car, 2 traffic lights, 184.9ms"YOLOResults.verboseSpeed()
- 返回 {string}
获取速度统计字符串
console.log(yoloResults.verboseSpeed());
// 输出: "Speed: 184.9ms preprocess, 45.6ms inference, 12.3ms postprocess per image at shape (1, 3, 640, 480)"YOLOResults.verboseSaved()
- 返回 {string}
获取保存成功信息
console.log(yoloResults.verboseSaved());
// 输出: "Results saved to /sdcard/YOLO/runs/detect/exp"YOLOResults.verboseCamera()
- 返回 {string}
获取相机详细的预测结果字符串
console.log(yoloResults.verboseCamera());
// 输出: 0: 640x480 1 person, 1 cell phone 123.4msYOLOResults.saveTxt([options])
options{Object} 可选path{string} 可选,保存的文件路径,默认为results.txt。saveConf{boolean} 可选,是否保存置信度,默认为false。
返回 {boolean}
将数据保存为 YOLO 格式标签文件.txt
每行表示一个检测目标:class centerX centerY width height [confidence]
yoloResults.saveTxt({
path: "/sdcard/results.txt",
saveConf: true
});YOLOResults.toDf([options])
options{object}(可选)DataFrame配置normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5
- 返回 {DataFrame}
转换为DataFrame格式
// 默认像素坐标
var df = yoloResults.toDf();
console.log("\nCSV (pixel):\n" + df.toCsv()); // 输出实际像素坐标
// 使用归一化坐标
var df2 = yoloResults.toDf({ normalize: true, decimals: 3 });
console.log("\nCSV (normalize):\n" + df2.toCsv()); // 输出归一化坐标(0~1)YOLOResults.toJson()
- 返回 {Array}
转换为JSON格式。
// 获取JSON数组
var json = yoloResults.toJson();
console.log(json);YOLOResults.toJson(path)
path{string} 保存的文件路径。返回 {boolean}
将JSON格式的数据保存到指定文件。
// 保存到文件
yoloResults.toJson("/sdcard/results.json");YOLOResults.toCsv([options])
options{object} 配置,可选normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5index: CSV 表格中是否显示行索引列,可选,默认true
- 返回 {string}
转换为 CSV 格式字符串。
var csv = yoloResults.toCsv({
normalize: false,
index: false,
decimals: 2,
});
console.log(csv);YOLOResults.toCsv(options)
options{object} 配置path: 保存的路径normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5index: CSV 表格中是否显示行索引列,可选,默认true
- 返回 {boolean}
保存为 CSV 文件。
yoloResults.toCsv({
path: "/sdcard/results.csv",
normalize: true,
index: true
});YOLOResults.toXml([options])
options{object} 配置,可选normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5index: XML 表格中是否显示行索引列,可选,默认true
- 返回 {string}
转换为 XML 格式字符串。
var xml = yoloResults.toXml({
normalize: false,
index: true
});
console.log(xml)YOLOResults.toXml(options)
options{object} 配置path: 保存的路径normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5index: XML 表格中是否显示行索引列,可选,默认true
- 返回 {boolean}
保存为 XML 文件。
yoloResults.toXml({
path: "/sdcard/results.xml",
normalize: true,
index: true
});YOLOResults.toHtml([options])
options{object} 配置,可选normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5index: HTML 表格中是否显示行索引列,可选,默认true
- 返回 {string}
转换为 HTML 格式字符串。
var html = yoloResults.toHtml({
normalize: false,
index: true
});
console.log(html)YOLOResults.toHtml(options)
options{object} 配置path: 保存的路径normalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5index: HTML 表格中是否显示行索引列,可选,默认true
- 返回 {boolean}
保存为 HTML 文件。
yoloResults.toHtml({
path: "/sdcard/results.html",
normalize: true,
index: true
});YOLOResults.toSql([options])
options{object}(可选)数据库配置path: 保存的路径,可选,默认results.dbtableName: 表名,可选,默认resultsnormalize{boolean} 是否归一化坐标,可选,默认falsedecimals{number} 小数位数,可选,默认5
- 返回 {boolean}
保存到SQLite数据库
yoloResults.toSql({
path: "/sdcard/results.db",
tableName: "detections"
});Speed
Speed 类存储 YOLO 推理各阶段的时间统计信息。 由 YOLOResults.speed 得到
⚡ 提示:想要进一步提高推理性能,请参考 推理速度 章节中的优化建议。
示例
// 访问速度信息
var yoloResults = yolo.predict(image);
var speed = yoloResults.speed;
// 格式化输出
console.log(speed);
// 输出: "Speed(preprocess=12.30ms, inference=48.50ms, postprocess=9.20ms, total=70.00ms)"
console.log("预处理时间:", speed.preprocess + "ms");
console.log("推理时间:", speed.inference + "ms");
console.log("后处理时间:", speed.postprocess + "ms");
console.log("总耗时:", (speed.preprocess + speed.inference + speed.postprocess) + "ms");Speed.preprocess
preprocess
图像预处理耗时(毫秒),包括图像加载、缩放、归一化等
Speed.inference
inference
模型推理耗时(毫秒),指在所选推理后端(CPU 或 GPU)上执行模型计算的时间
Speed.postprocess
postprocess
后处理耗时(毫秒),包括 NMS、结果解码、坐标转换等
Boxes
Boxes 类表示边界框检测结果。
示例
var boxes = yoloResults.boxes();
if (boxes) {
console.log("=== Boxes.size() ===");
console.log("目标数量: " + boxes.size());
console.log("\n=== Boxes.xyxy() ===");
var allXYXY = boxes.xyxy();
for (var i = 0; i < allXYXY.length; i++) {
var xyxy = allXYXY[i];
console.log("框 #" + i + ": [" + xyxy[0] + ", " + xyxy[1] + ", " + xyxy[2] + ", " + xyxy[3] + "]");
}
console.log("\n=== Boxes.xyxy(index) ===");
for (var i = 0; i < boxes.size(); i++) {
var xyxy = boxes.xyxy(i);
console.log("框 #" + i + ": [" + xyxy[0] + ", " + xyxy[1] + ", " + xyxy[2] + ", " + xyxy[3] + "]");
}
console.log("\n=== Boxes.xyxyn() ===");
var allXYXN = boxes.xyxyn();
for (var i = 0; i < allXYXN.length; i++) {
var xyn = allXYXN[i];
console.log("框 #" + i + " 归一化: [" + xyn[0] + ", " + xyn[1] + ", " + xyn[2] + ", " + xyn[3] + "]");
}
console.log("\n=== Boxes.xyxyn(index) ===");
for (var i = 0; i < boxes.size(); i++) {
var xyn = boxes.xyxyn(i);
console.log("框 #" + i + ": [" + xyn[0] + ", " + xyn[1] + ", " + xyn[2] + ", " + xyn[3] + "]");
}
console.log("\n=== Boxes.xywh() ===");
var allXYWH = boxes.xywh();
for (var i = 0; i < allXYWH.length; i++) {
var xywh = allXYWH[i];
console.log("框 #" + i + " 中心+宽高: [" + xywh[0] + ", " + xywh[1] + ", " + xywh[2] + ", " + xywh[3] + "]");
}
console.log("\n=== Boxes.xywh(index) ===");
for (var i = 0; i < boxes.size(); i++) {
var xywh = boxes.xywh(i);
console.log("框 #" + i + ": [" + xywh[0] + ", " + xywh[1] + ", " + xywh[2] + ", " + xywh[3] + "]");
}
console.log("\n=== Boxes.xywhn() ===");
var allXYWHN = boxes.xywhn();
for (var i = 0; i < allXYWHN.length; i++) {
var xywhn = allXYWHN[i];
console.log("框 #" + i + " 归一化中心+宽高: [" + xywhn[0] + ", " + xywhn[1] + ", " + xywhn[2] + ", " + xywhn[3] + "]");
}
console.log("\n=== Boxes.xywhn(index) ===");
for (var i = 0; i < boxes.size(); i++) {
var xywhn = boxes.xywhn(i);
console.log("框 #" + i + ": [" + xywhn[0] + ", " + xywhn[1] + ", " + xywhn[2] + ", " + xywhn[3] + "]");
}
console.log("\n=== Boxes.cls() ===");
var allCls = boxes.cls();
for (var i = 0; i < allCls.length; i++) {
console.log("框 #" + i + " 类别ID: " + allCls[i]);
}
console.log("\n=== Boxes.cls(index) ===");
for (var i = 0; i < boxes.size(); i++) {
console.log("框 #" + i + ": 类别ID " + boxes.cls(i));
}
console.log("\n=== Boxes.conf() ===");
var allConf = boxes.conf();
for (var i = 0; i < allConf.length; i++) {
console.log("框 #" + i + " 置信度: " + allConf[i]);
}
console.log("\n=== Boxes.conf(index) ===");
for (var i = 0; i < boxes.size(); i++) {
console.log("框 #" + i + ": 置信度 " + boxes.conf(i));
}
} else {
console.error("当前任务不是目标检测、实例分割、姿态估计任务");
}Boxes.size()
- 返回 {number}
获取边界框数量
Boxes.xyxy()
- 返回 {float[][]}
获取所有边界框的 [x1, y1, x2, y2] 坐标
Boxes.xyxy(index)
index{number} 目标索引- 返回 {float[]}
获取单个边界框的 [x1, y1, x2, y2] 坐标
Boxes.xyxyn()
- 返回 {float[][]}
获取归一化的 [x1, y1, x2, y2] 坐标
Boxes.xyxyn(index)
index{number} 目标索引- 返回 {float[]}
获取单个目标的归一化 [x1, y1, x2, y2] 坐标
Boxes.xywh()
- 返回 {float[][]}
获取 [x_center, y_center, width, height] 坐标
Boxes.xywh(index)
index{number} 目标索引- 返回 {float[]}
获取单个边界框的 [x_center, y_center, width, height] 坐标
Boxes.xywhn()
- 返回 {float[][]}
获取归一化的 [x_center, y_center, width, height] 坐标
Boxes.xywhn(index)
index{number} 目标索引- 返回 {float[]}
获取单个目标的归一化 [x_center, y_center, width, height] 坐标
Boxes.cls()
- 返回 {number[]}
获取所有类别ID数组
Boxes.cls(index)
index{number} 目标索引- 返回 {number}
获取单个目标的类别ID
Boxes.conf()
- 返回 {float[]}
获取所有置信度数组
Boxes.conf(index)
index{number} 目标索引- 返回 {float}
获取单个目标的置信度
Masks
Masks 类表示分割掩码结果。
示例
var masks = yoloResults.masks();
if (masks) {
// 1. 打印掩码总数(核心基础信息)
console.log("=== 掩码基础信息 ===");
console.log("掩码数量: " + masks.size());
// 2. Masks.xy() - 所有目标原始轮廓坐标(仅打印前5个点)
console.log("\n=== Masks.xy() 所有目标原始轮廓坐标 ===");
var allXY = masks.xy();
for (var i = 0; i < allXY.length; i++) {
var xy = allXY[i];
console.log("目标 #" + i + " 轮廓坐标(总点数:" + xy.length + "):");
for (var j = 0; j < xy.length; j++) {
if (j >= 5) {
// 仅打印前5个点
console.log(" (省略剩余 " + (xy.length - 5) + " 个点)");
break;
}
console.log(" 点" + j + ": [" + xy[j][0] + ", " + xy[j][1] + "]");
}
}
// 3. Masks.xy(index) - 按索引获取单个目标原始轮廓坐标(仅打印前5个点)
console.log("\n=== Masks.xy(index) 按索引获取原始轮廓坐标 ===");
for (var i = 0; i < masks.size(); i++) {
var xy = masks.xy(i);
console.log("目标 #" + i + " 轮廓坐标(总点数:" + xy.length + "):");
for (var j = 0; j < xy.length; j++) {
if (j >= 5) {
// 仅打印前5个点
console.log(" (省略剩余 " + (xy.length - 5) + " 个点)");
break;
}
console.log(" 点" + j + ": [" + xy[j][0] + ", " + xy[j][1] + "]");
}
}
// 4. Masks.xyn() - 所有目标归一化轮廓坐标(仅打印前5个点,保留4位小数)
console.log("\n=== Masks.xyn() 所有目标归一化轮廓坐标 ===");
var allXYN = masks.xyn();
for (var i = 0; i < allXYN.length; i++) {
var xyn = allXYN[i];
console.log("目标 #" + i + " 归一化坐标(总点数:" + xyn.length + "):");
for (var j = 0; j < xyn.length; j++) {
if (j >= 5) {
// 仅打印前5个点
console.log(" (省略剩余 " + (xyn.length - 5) + " 个点)");
break;
}
// 归一化坐标保留4位小数,精简显示
console.log(" 点" + j + ": [" + xyn[j][0].toFixed(4) + ", " + xyn[j][1].toFixed(4) + "]");
}
}
// 5. Masks.xyn(index) - 按索引获取单个目标归一化轮廓坐标(仅打印前5个点)
console.log("\n=== Masks.xyn(index) 按索引获取归一化轮廓坐标 ===");
for (var i = 0; i < masks.size(); i++) {
var xyn = masks.xyn(i);
console.log("目标 #" + i + " 归一化坐标(总点数:" + xyn.length + "):");
for (var j = 0; j < xyn.length; j++) {
if (j >= 5) {
// 仅打印前5个点
console.log(" (省略剩余 " + (xyn.length - 5) + " 个点)");
break;
}
console.log(" 点" + j + ": [" + xyn[j][0].toFixed(4) + ", " + xyn[j][1].toFixed(4) + "]");
}
}
// 6. 轮廓绘制
console.log("\n=== Masks.draw([img]) 轮廓绘制 ===");
var originalImg = images.read("/sdcard/assets/image/bus.jpg");
var drawnImg = masks.draw(originalImg);
drawnImg.saveTo("/sdcard/drawnImg.png");
console.log("✅ 轮廓已绘制并保存至: /sdcard/drawnImg.png");
originalImg.recycle();
drawnImg.recycle();
} else {
console.error("❌ 当前任务不是实例分割,无掩码数据");
}Masks.size()
- 返回 {number}
获取掩码数量
Masks.xy()
- 返回 {float[][][]}
获取所有轮廓的原始坐标
Masks.xy(index)
index{number} 目标索引- 返回 {float[][]}
获取单个目标的轮廓坐标
Masks.xyn()
- 返回 {float[][][]}
获取所有轮廓的归一化坐标
Masks.xyn(index)
index{number} 目标索引- 返回 {float[][]}
获取单个目标的归一化轮廓坐标
Masks.draw(img)
在指定图像上绘制分割轮廓,并返回绘制后的新图像对象。
返回的 Image 对象为新实例,使用完毕后必须手动调用 Image.recycle() 回收资源,避免内存泄漏。
Keypoints
Keypoints 类表示关键点检测结果。
示例
var keypoints = yoloResults.keypoints();
if (keypoints) {
// 1. 打印关键点目标总数
console.log("=== 关键点基础信息 ===");
console.log("目标数量: " + keypoints.size());
// 2. Keypoints.xy() - 所有目标关键点原始坐标(逐行打印)
console.log("\n=== Keypoints.xy() 所有目标关键点原始坐标 ===");
var allXY = keypoints.xy();
for (var i = 0; i < allXY.length; i++) {
var kpArray = allXY[i];
console.log("目标 #" + i + " 关键点(共" + kpArray.length + "个):");
for (var j = 0; j < kpArray.length; j++) {
console.log(" 关键点" + j + ": [" + kpArray[j][0] + ", " + kpArray[j][1] + "]");
}
}
// 3. Keypoints.xy(index) - 按索引获取单个目标关键点原始坐标(逐行打印)
console.log("\n=== Keypoints.xy(index) 按索引获取关键点原始坐标 ===");
for (var i = 0; i < keypoints.size(); i++) {
var kpArray = keypoints.xy(i);
console.log("目标 #" + i + " 关键点(共" + kpArray.length + "个):");
for (var j = 0; j < kpArray.length; j++) {
console.log(" 关键点" + j + ": [" + kpArray[j][0] + ", " + kpArray[j][1] + "]");
}
}
// 4. Keypoints.xyn() - 所有目标归一化关键点坐标(逐行打印,原始数值)
console.log("\n=== Keypoints.xyn() 所有目标归一化关键点坐标 ===");
var allXYN = keypoints.xyn();
for (var i = 0; i < allXYN.length; i++) {
var kpArray = allXYN[i];
console.log("目标 #" + i + " 归一化关键点(共" + kpArray.length + "个):");
for (var j = 0; j < kpArray.length; j++) {
// 完全保留原始数值,不做任何小数位数处理
console.log(" 关键点" + j + ": [" + kpArray[j][0] + ", " + kpArray[j][1] + "]");
}
}
// 5. Keypoints.xyn(index) - 按索引获取单个目标归一化关键点坐标(逐行打印)
console.log("\n=== Keypoints.xyn(index) 按索引获取归一化关键点坐标 ===");
for (var i = 0; i < keypoints.size(); i++) {
var kpArray = keypoints.xyn(i);
console.log("目标 #" + i + " 归一化关键点(共" + kpArray.length + "个):");
for (var j = 0; j < kpArray.length; j++) {
console.log(" 关键点" + j + ": [" + kpArray[j][0] + ", " + kpArray[j][1] + "]");
}
}
// 6. Keypoints.conf() - 所有目标关键点置信度(逐行打印,原始数值)
console.log("\n=== Keypoints.conf() 所有目标关键点置信度 ===");
var allConf = keypoints.conf();
for (var i = 0; i < allConf.length; i++) {
var confArray = allConf[i];
console.log("目标 #" + i + " 关键点置信度(共" + confArray.length + "个):");
for (var j = 0; j < confArray.length; j++) {
// 完全保留原始数值,不做任何小数位数处理
console.log(" 关键点" + j + "置信度: " + confArray[j]);
}
}
// 7. Keypoints.conf(index) - 按索引获取单个目标关键点置信度(逐行打印)
console.log("\n=== Keypoints.conf(index) 按索引获取关键点置信度 ===");
for (var i = 0; i < keypoints.size(); i++) {
var confArray = keypoints.conf(i);
console.log("目标 #" + i + " 关键点置信度(共" + confArray.length + "个):");
for (var j = 0; j < confArray.length; j++) {
console.log(" 关键点" + j + "置信度: " + confArray[j]);
}
}
} else {
console.error("当前任务不是姿态估计,无关键点数据");
}Keypoints.size()
- 返回 {number}
获取目标数量
Keypoints.xy()
- 返回 {float[][][]}
获取所有关键点的原始坐标
Keypoints.xy(index)
index{number} 目标索引- 返回 {float[][]}
获取单个目标的关键点坐标
Keypoints.xyn()
- 返回 {float[][][]}
获取所有关键点的归一化坐标
Keypoints.xyn(index)
index{number} 目标索引- 返回 {float[][]}
获取单个目标的归一化关键点坐标
Keypoints.conf()
- 返回 {float[][]}
获取所有关键点的置信度
Keypoints.conf(index)
index{number} 目标索引- 返回 {float[]}
获取单个目标的关键点置信度
OBB
OBB 类表示旋转框检测结果,包含获取旋转框角点、尺寸、类别等信息的方法。
示例
var obb = yoloResults.obb();
if (obb) {
console.log("=== OBB.size() ===");
console.log("旋转框数量: " + obb.size());
console.log("\n=== OBB.xywhr() ===");
var allXYWHR = obb.xywhr();
for (var i = 0; i < allXYWHR.length; i++) {
var arr = allXYWHR[i];
console.log(
"旋转框 #" +
i +
": [x_center=" +
arr[0] +
", y_center=" +
arr[1] +
", w=" +
arr[2] +
", h=" +
arr[3] +
", r=" +
arr[4] +
"]"
);
}
console.log("\n=== OBB.xywhr(index) ===");
for (var i = 0; i < obb.size(); i++) {
var arr = obb.xywhr(i);
console.log(
"旋转框 #" +
i +
": [x_center=" +
arr[0] +
", y_center=" +
arr[1] +
", w=" +
arr[2] +
", h=" +
arr[3] +
", r=" +
arr[4] +
"]"
);
}
console.log("\n=== OBB.xyxyxyxy() ===");
var allCorners = obb.xyxyxyxy();
for (var i = 0; i < allCorners.length; i++) {
var cornerArr = allCorners[i];
var str = "旋转框 #" + i + " 四角: [";
for (var j = 0; j < cornerArr.length; j++) {
str += "[" + cornerArr[j][0] + ", " + cornerArr[j][1] + "]";
if (j < cornerArr.length - 1) str += ", ";
}
str += "]";
console.log(str);
}
console.log("\n=== OBB.xyxyxyxy(index) ===");
for (var i = 0; i < obb.size(); i++) {
var cornerArr = obb.xyxyxyxy(i);
var str = "旋转框 #" + i + " 四角: [";
for (var j = 0; j < cornerArr.length; j++) {
str += "[" + cornerArr[j][0] + ", " + cornerArr[j][1] + "]";
if (j < cornerArr.length - 1) str += ", ";
}
str += "]";
console.log(str);
}
console.log("\n=== OBB.xyxyxyxyn() ===");
var allCornersN = obb.xyxyxyxyn();
for (var i = 0; i < allCornersN.length; i++) {
var cornerArr = allCornersN[i];
var str = "旋转框 #" + i + " 归一化四角: [";
for (var j = 0; j < cornerArr.length; j++) {
str += "[" + cornerArr[j][0] + ", " + cornerArr[j][1] + "]";
if (j < cornerArr.length - 1) str += ", ";
}
str += "]";
console.log(str);
}
console.log("\n=== OBB.xyxyxyxyn(index) ===");
for (var i = 0; i < obb.size(); i++) {
var cornerArr = obb.xyxyxyxyn(i);
var str = "旋转框 #" + i + " 归一化四角: [";
for (var j = 0; j < cornerArr.length; j++) {
str += "[" + cornerArr[j][0] + ", " + cornerArr[j][1] + "]";
if (j < cornerArr.length - 1) str += ", ";
}
str += "]";
console.log(str);
}
console.log("\n=== OBB.xyxy() ===");
var allXY = obb.xyxy();
for (var i = 0; i < allXY.length; i++) {
var arr = allXY[i];
console.log("旋转框 #" + i + " 轴对齐框: [x1=" + arr[0] + ", y1=" + arr[1] + ", x2=" + arr[2] + ", y2=" + arr[3] + "]");
}
console.log("\n=== OBB.xyxy(index) ===");
for (var i = 0; i < obb.size(); i++) {
var arr = obb.xyxy(i);
console.log("旋转框 #" + i + " 轴对齐框: [x1=" + arr[0] + ", y1=" + arr[1] + ", x2=" + arr[2] + ", y2=" + arr[3] + "]");
}
console.log("\n=== OBB.conf() ===");
var confs = obb.conf();
for (var i = 0; i < confs.length; i++) {
console.log("旋转框 #" + i + " 置信度: " + confs[i]);
}
console.log("\n=== OBB.conf(index) ===");
for (var i = 0; i < obb.size(); i++) {
console.log("旋转框 #" + i + " 置信度: " + obb.conf(i));
}
console.log("\n=== OBB.cls() ===");
var clsArr = obb.cls();
for (var i = 0; i < clsArr.length; i++) {
console.log("旋转框 #" + i + " 类别ID: " + clsArr[i]);
}
console.log("\n=== OBB.cls(index) ===");
for (var i = 0; i < obb.size(); i++) {
console.log("旋转框 #" + i + " 类别ID: " + obb.cls(i));
}
} else {
console.error("当前任务不是旋转框检测");
}OBB.size()
- 返回 {number}
获取旋转框的数量。
OBB.xywhr()
- 返回 {float[][]}
获取旋转框的 [x_center, y_center, width, height, radians] 格式,表示旋转框的中心坐标、尺寸和旋转弧度。
其中:
radians为弧度(radians)- 角度 =
radians × 180 / Math.PI
OBB.xywhr(index)
index{number}:目标索引。- 返回 {float[]}
获取指定索引的旋转框 [x_center, y_center, width, height, radians] 格式。
OBB.xyxyxyxy()
- 返回 {float[][][]}
获取旋转框的四个角点坐标,顺序为:右下 -> 右上 -> 左上 -> 左下。
OBB.xyxyxyxy(index)
index{number}:目标索引。- 返回 {float[][]}
获取指定索引的旋转框的四个角点坐标,顺序为:右下 -> 右上 -> 左上 -> 左下。
OBB.xyxyxyxyn()
- 返回 {float[][][]} 获取归一化的四个角点坐标,顺序为:右下 -> 右上 -> 左上 -> 左下。
OBB.xyxyxyxyn(index)
index{number}:目标索引。- 返回 {float[][]}
获取指定索引的归一化四个角点坐标,顺序为:右下 -> 右上 -> 左上 -> 左下。
OBB.xyxy()
- 返回 {float[][]}
获取轴对齐边界框的左上和右下坐标。
OBB.xyxy(index)
index{number}:目标索引。- 返回 {float[]}
获取指定索引的轴对齐边界框左上和右下坐标。
OBB.conf()
- 返回 {float[]}
获取每个旋转框的置信度数组。
OBB.conf(index)
index{number}:目标索引。- 返回 {float}
获取指定索引的旋转框的置信度。
OBB.cls()
- 返回 {number[]}
获取每个旋转框的类别ID数组。
OBB.cls(index)
index{number}:目标索引。- 返回 {number}
获取指定索引的旋转框的类别ID。
Probs
Probs 类表示分类概率结果。
示例
var probs = yoloResults.probs();
if (probs) {
console.log("=== Probs 测试示例 ===");
// 1. Top1 ID
var top1Id = probs.top1();
console.log("Top1 类别ID: " + top1Id);
// 2. Top1 名称
var top1Name = probs.top1name();
console.log("Top1 类别名称: " + top1Name);
// 3. Top1 置信度
var top1Conf = probs.top1conf();
console.log("Top1 置信度: " + top1Conf);
// 4. Top1 完整对象
var top1Obj = probs.top1Object();
if (top1Obj) {
console.log("Top1 完整对象信息:");
console.log(" cls: " + top1Obj.cls);
console.log(" conf: " + top1Obj.conf);
} else {
console.log("Top1 对象为空");
}
// 5. Top5 ID 数组
var top5Ids = probs.top5();
console.log("Top5 类别ID数组: " + top5Ids);
// 6. Top5 名称数组
var top5Names = probs.top5name();
console.log("Top5 类别名称数组: " + top5Names);
// 7. Top5 置信度数组
var top5Confs = probs.top5conf();
console.log("Top5 置信度数组: " + top5Confs);
// 8. 输出 Top5 详细信息
console.log("\n=== Top5 分类详细信息 ===");
for (var i = 0; i < top5Ids.length; i++) {
console.log(
"Top" + (i + 1) + ": ID=" + top5Ids[i] + ", 名称=" + top5Names[i] + ", 置信度=" + (top5Confs[i] * 100).toFixed(2) + "%"
);
}
// 9. Probs.summary() 简要摘要
var summary = probs.summary();
console.log("\n分类摘要: " + summary);
} else {
console.error("当前任务不是分类任务,无概率结果");
}Probs.top1()
- 返回 {number}
获取Top1类别ID
Probs.top1name()
- 返回 {string}
获取Top1类别名称
Probs.top1conf()
- 返回 {float}
获取Top1置信度
Probs.top1Object()
- 返回 {YOLOObject | null}
获取Top1完整对象
Probs.top5()
- 返回 {number[]}
获取Top5类别ID数组
Probs.top5name()
- 返回 {string[]}
获取Top5类别名称数组
Probs.top5conf()
- 返回 {float[]}
获取Top5置信度数组
Probs.summary()
- 返回 {string}
获取简要摘要字符串
DataFrame
DataFrame 类提供结构化数据操作和文件导出功能,适用于处理 YOLO 推理结果。
示例
// 创建 DataFrame
var df = yoloResults.toDf({
normalize: false, // 是否归一化
decimals: 2, // 小数保留位数
});
console.log("=== DataFrame.shape() ===");
var shape = df.shape(); // 返回 [行数, 列数]
console.log("行数: " + shape[0] + ", 列数: " + shape[1]);
console.log("\n=== DataFrame.head(n) ===");
var head = df.head(5); // 获取前 5 行
console.log(head);
for (var i = 0; i < head.length; i++) {
var summary = head[i];
console.log("目标 #" + i + ": cls=" + summary.cls + ", name=" + summary.name + ", confidence=" + summary.confidence);
// 其他数据参阅 Summary,例如 box, obbBox, keypoints, segments 等
}
console.log("\n=== DataFrame.toJson() ===");
var jsonStr = df.toJson(); // 转换为 JSON 字符串
console.log(jsonStr);
var jsonSave = df.toJson({ path: "/sdcard/results.json" }); // 保存 JSON 文件
console.log("保存 JSON 文件结果:", jsonSave);
console.log("\n=== DataFrame.toCsv() ===");
var csvStr = df.toCsv({ index: true }); // 转换为 CSV 字符串,显示行索引
console.log(csvStr);
var csvSave = df.toCsv({ path: "/sdcard/results.csv", index: true }); // 保存 CSV 文件
console.log("保存 CSV 文件结果:", csvSave);
console.log("\n=== DataFrame.toHtml() ===");
var htmlStr = df.toHtml({ index: true }); // 转换为 HTML 字符串
console.log(htmlStr);
var htmlSave = df.toHtml({ path: "/sdcard/results.html", index: true }); // 保存 HTML 文件
console.log("保存 HTML 文件结果:", htmlSave);
console.log("\n=== DataFrame.toXml() ===");
var xmlStr = df.toXml({ index: true }); // 转换为 XML 字符串
console.log(xmlStr);
var xmlSave = df.toXml({ path: "/sdcard/results.xml", index: false }); // 保存 XML 文件,不显示行索引列
console.log("保存 XML 文件结果:", xmlSave);
console.log("\n=== DataFrame.toSql() ===");
var sqlSave = df.toSql({
path: "/sdcard/results.db",
tableName: "detection_results",
});
console.log("保存 SQLite 数据库结果:", sqlSave);DataFrame.shape()
- 返回 {number[]}
获取 DataFrame 形状 [行数, 列数]。
DataFrame.head([n])
n{number}(可选)行数,默认5- 返回 {Summary[]}
获取前 n 行数据。
DataFrame.saveTxt(path[, saveConf])
path{string} 保存的文件路径。saveConf{boolean} 可选,是否保存置信度,默认为false。返回 {boolean}
将数据保存为 YOLO 格式标签文件.txt
DataFrame.saveTxt([options])
options{Object} 包括:path{string} 可选,保存的文件路径,默认为results.txt。saveConf{boolean} 可选,是否保存置信度,默认为false。
返回 {boolean}
将数据保存为 YOLO 格式标签文件.txt
DataFrame.toJson()
- 返回 {Array}
转换为JSON格式。
DataFrame.toJson(path)
path{string} 保存的文件路径。返回 {boolean}
将JSON格式的数据保存到指定文件。
DataFrame.toCsv([index])
index{boolean} 是否显示行索引列,可选,默认true- 返回 {string}
转换为 CSV 格式字符串。
DataFrame.toCsv(path[, index])
path{string} 保存的文件路径。index{boolean} CSV 表格中是否显示行索引列,可选,默认true- 返回 {boolean}
保存为 CSV 文件。
DataFrame.toCsv(options)
options{object} 配置path: 保存的路径,可选,默认results.csvindex: CSV 表格中是否显示行索引列,可选,默认true
- 返回 {boolean}
保存为 CSV 文件。
DataFrame.toXml([index])
index{boolean} 是否显示行索引列,可选,默认true- 返回 {string}
转换为 XML 格式字符串。
DataFrame.toXml(path[, index])
path{string} 保存的文件路径。index{boolean} XML 表格中是否显示行索引列,可选,默认true- 返回 {boolean}
保存为 XML 文件。
DataFrame.toXml(options)
options{object} 配置path{string} 保存的路径,可选,默认results.xmlindex{boolean} XML 表格中是否显示行索引列,可选,默认true
- 返回 {boolean}
保存为 XML 文件。
DataFrame.toHtml([index])
index{boolean} 是否显示行索引列,可选,默认true- 返回 {string}
转换为 HTML 格式字符串。
DataFrame.toHtml(path[, index])
path{string} 保存的文件路径。index{boolean} HTML 表格中是否显示行索引列,可选,默认true- 返回 {boolean}
保存为 HTML 文件。
DataFrame.toHtml(options)
options{object} 配置path{string} 保存的路径,可选,默认results.htmlindex{boolean} HTML 表格中是否显示行索引列,可选,默认true
- 返回 {boolean}
保存为 HTML 文件。
DataFrame.toSql(path[, tableName])
path{string} 保存的路径tableName{string} 表名,可选,默认results- 返回 {boolean}
将数据保存到 SQLite 数据库。
DataFrame.toSql([options])
options{object}(可选)数据库配置path: 保存的路径,可选,默认results.dbtableName: 表名,可选,默认results
- 返回 {boolean}
将数据保存到 SQLite 数据库。
Summary
Summary 表示单个检测目标的摘要信息,包含通用字段和各任务专属字段,字段为动态存在(非当前任务的字段为null)。
示例
// 获取摘要数组
var summaries = yoloResults.summary();
// 遍历摘要信息
if (summaries.length > 0) {
for (var i = 0; i < summaries.length; i++) {
var summary = summaries[i];
console.log("=== 目标 #" + i + " ===");
console.log("类别名称: " + summary.name + ",类别ID: " + summary.cls);
console.log("置信度: " + summary.confidence);
// 边界框信息(Box)
if (summary.box) {
if ([0, 1, 3].includes(yolo.task)) {
// 目标检测、实例分割、姿态估计(轴对齐边界框)
console.log(
"边界框 (Axis-Aligned Box): 左上=(" +
summary.box.x1 +
", " +
summary.box.y1 +
"), " +
"右下=(" +
summary.box.x2 +
", " +
summary.box.y2 +
")"
);
} else if (yolo.task === 4) {
// 旋转框四角
console.log("旋转框四角点 (右下 → 右上 → 左上 → 左下):");
console.log(
" 右下: (" +
summary.box.x1 +
", " +
summary.box.y1 +
")\n" +
" 右上: (" +
summary.box.x2 +
", " +
summary.box.y2 +
")\n" +
" 左上: (" +
summary.box.x3 +
", " +
summary.box.y3 +
")\n" +
" 左下: (" +
summary.box.x4 +
", " +
summary.box.y4 +
")"
);
}
}
// 分割掩码信息 (Segments) - 掩码是目标轮廓的坐标点集合,用于精准定位目标边缘
if (summary.segments) {
// 获取掩码的X坐标数组和Y坐标数组
var xs = summary.segments.x;
var ys = summary.segments.y;
// 先打印掩码坐标点的总数,让用户知道完整数据量
console.log("分割掩码坐标点总数: " + xs.length + " 个");
console.log("分割掩码前5个坐标点(避免输出过多数据):");
// 遍历坐标点,逐个打印
for (var s = 0; s < xs.length; s++) {
// 核心判断:如果当前索引>=5(即已经打印了前5个点),直接跳出循环停止打印
if (s >= 5) {
// 打印提示信息,告知用户已停止打印
console.log(" 提示:已打印前5个坐标点,剩余 " + (xs.length - 5) + " 个点不再展示");
break; // 跳出循环,终止后续打印
}
var segX = xs[s]; // 当前点的X坐标
var segY = ys[s]; // 当前点的Y坐标
console.log(" 坐标点 #" + (s + 1) + ": (" + segX + ", " + segY + ")");
}
}
// 关键点信息 (Keypoints)
if (summary.keypoints) {
var xs = summary.keypoints.x;
var ys = summary.keypoints.y;
var visible = summary.keypoints.visible;
for (var k = 0; k < xs.length; k++) {
console.log("关键点 #" + k + ": (x=" + xs[k] + ", y=" + ys[k] + ", 可见性=" + visible[k] + ")");
}
}
console.log("--------------------------------------------------");
}
} else {
console.error("未检测到目标或摘要为空");
}Summary.cls
- {number}
类别ID
Summary.name
- {string}
类别名称
Summary.confidence
- {float}
置信度(0~1)
Summary.box
box{Object | null} 边界框信息x1,y1,x2,y2{float} 矩形框,轴对齐边界框坐标x1,y1,x2,y2,x3,y3,x4,y4{float} 旋转框,4个角点坐标
Summary.segments
segments{Object | null}x{float[]} 分割轮廓的 x 坐标数组y{float[]} 分割轮廓的 y 坐标数组 分割轮廓信息
Summary.keypoints
keypoints{Object | null}x{float[]} 关键点 x 坐标数组y{float[]} 关键点 y 坐标数组visible{float[]} 关键点 可见性(置信度)数组
姿态的关键点信息
YOLOObject
单个推理对象
示例
// 遍历每一个 YOLOObject(目标检测结果)
for (var i = 0; i < yoloResults.size(); i++) {
var yoloObject = yoloResults.get(i);
// 打印目标的基本信息
console.log("目标 " + (i + 1) + ":");
console.log(" 类别ID: " + yoloObject.cls);
var name = yoloResults.names[yoloObject.cls];
console.log(" 类别名称: " + name);
console.log(" 置信度: " + yoloObject.conf);
// 打印目标的位置信息(坐标和尺寸)
if ([0, 1, 3].includes(yolo.task)) {
// 目标检测、实例分割、姿态估计(轴对齐边界框)
console.log(" 检测框:");
console.log(" 左上角: x=" + yoloObject.x + ", y=" + yoloObject.y);
console.log(" 宽度=" + yoloObject.w + ", 高度=" + yoloObject.h);
} else if (yolo.task === 4) {
// 旋转框
console.log(" 旋转框:");
console.log(" 中心点: x=" + yoloObject.x + ", y=" + yoloObject.y);
console.log(" 宽度=" + yoloObject.w + ", 高度=" + yoloObject.h);
console.log(" 旋转角度=" + yoloObject.angle + "°");
}
// 打印关键点信息(如果有)
if (yoloObject.keypoints && yoloObject.keypoints.length > 0) {
console.log(" 关键点数量: " + yoloObject.keypoints.length);
for (var j = 0; j < yoloObject.keypoints.length; j++) {
var keypoint = yoloObject.keypoints[j];
console.log(" 关键点 " + (j + 1) + ": x=" + keypoint.x + ", y=" + keypoint.y + ", 可见性/置信度=" + keypoint.conf);
}
}
// ========== 补充:完整打印掩膜(mask)相关信息 ==========
console.log(" 掩膜(Mask)信息:");
// 打印mask的行列数
console.log(" 掩膜行数(maskRows): " + (yoloObject.maskRows || 0));
console.log(" 掩膜列数(maskCols): " + (yoloObject.maskCols || 0));
// 打印mask数据
if (yoloObject.maskData && yoloObject.maskData.length > 0) {
console.log(" 掩膜数据长度: " + yoloObject.maskData.length);
// 可选:打印前10个数据示例(避免数据量过大)
var sampleData = yoloObject.maskData.slice(0, 10);
console.log(" 掩膜数据前10个字节示例: " + sampleData.join(", "));
} else {
console.log(" 掩膜数据: 无");
}
// ========== 补充:完整打印轮廓(contours)相关信息 ==========
if (yoloObject.contours && yoloObject.contours.length > 0) {
console.log(" 轮廓(Contours)信息:");
console.log(" 轮廓总数: " + yoloObject.contours.length);
for (var k = 0; k < yoloObject.contours.length; k++) {
var contour = yoloObject.contours[k];
console.log(" 轮廓 " + (k + 1) + ":");
console.log(" 该轮廓的点数量: " + (contour ? contour.length : 0));
if (contour && contour.length > 0) {
// 打印前5个点(避免输出过多)
var printCount = Math.min(contour.length, 5);
for (var pointIndex = 0; pointIndex < printCount; pointIndex++) {
var point = contour[pointIndex];
// 兼容点数据的不同格式(int[] 或 float[])
console.log(" 点 " + (pointIndex + 1) + ": x=" + point[0] + ", y=" + point[1]);
}
// 如果点数量超过5,提示省略部分
if (contour.length > 5) {
console.log(" ... 省略 " + (contour.length - 5) + " 个点");
}
} else {
console.log(" 该轮廓无数据");
}
}
} else {
console.log(" 轮廓(Contours)信息: 无");
}
console.log("--------------------");
}YOLOObject.x
- {float}
左上角的 x 坐标(除旋转外)。旋转时,代表中心点的 x 坐标。
YOLOObject.y
- {float}
左上角的 y 坐标(除旋转外)。旋转时,代表中心点的 y 坐标。
YOLOObject.w
- {float}
目标的宽度(除旋转外)。旋转时,代表目标的宽度。
YOLOObject.h
- {float}
目标的高度(除旋转外)。旋转时,代表目标的高度。
YOLOObject.angle
- {float}
目标的旋转角度(度,OpenCV 标准:0~360度,有些系统用 -180~180度)。
YOLOObject.cls
- {number}
目标的类别ID。
YOLOObject.conf
- {float}
目标的置信度(0~1)。
YOLOObject.maskRows
- {number}
目标的掩膜行数。
YOLOObject.maskCols
- {number}
目标的掩膜列数。
YOLOObject.maskData
maskData{byte[]}
目标的掩膜数据。
YOLOObject.keypoints
- {List<KeyPoint>}
目标的关键点信息。
YOLOObject.contours
- {List<List<number[]>>}
目标的轮廓信息。每个轮廓点使用 float[2] 表示坐标。
YOLOObject.bounds()
- {Rect}
获取目标的边界框(Rect)。
- 当
angle = 0时,返回模型输出的原始边界矩形(左上角 + 宽高)。 - 当
angle ≠ 0时,返回 旋转后的最小包围矩形(Axis-Aligned Bounding Box, AABB),即包含旋转目标的最小矩形,等同于 OBB.xyxy() 得到的左上角和右下角坐标矩形。
KeyPoint
单个关键点对象(通常用于姿态估计或人体关键点检测)
KeyPoint.x
- {float}
关键点的横坐标(像素单位),通常相对于输入图像的左上角。
KeyPoint.y
- {float}
关键点的纵坐标(像素单位),通常相对于输入图像的左上角。
KeyPoint.conf
- {float}
关键点的置信度(可见性),取值范围 0~1,表示模型对该关键点预测的可信程度。
FloatImage
FloatImage 表示一个用于显示图像的悬浮窗对象,支持动态更新图像、设置标题、调整位置和大小,以及关闭窗口。
通常通过 YOLOResults.show() 获取实例。
FloatImage.setTitle(title)
title{string} 标题文本
设置悬浮窗标题。
FloatImage.setPosition(x, y)
x{number} X 坐标(像素)y{number} Y 坐标(像素)
设置悬浮窗位置。坐标基于屏幕左上角。
FloatImage.setSize(width, height)
width{number} 宽度(像素)height{number} 高度(像素)
设置悬浮窗显示尺寸。
FloatImage.close()
关闭悬浮窗并释放资源。
关闭后悬浮窗不可再使用。
