跳到主要内容

推理

m.infer("a.jpg"); m.infer(bytes); m.infer(image);

调用失败不抛异常,错误留在 AiResult 与 getLastError(),模型 Phase 保持 Opened。

快速开始​

Model m = new Model("yolov8n.darmodel");
if (!m.open()) {
System.out.println(m.getLastError());
return;
}
AiResult<InferenceResult> r = m.inferFile("photo.jpg");
if (r.isSuccess()) {
for (InferenceItem it : r.getContent().items())
System.out.println(it.label() + " " + it.score());
}
m.close();

基础用法​

inferFile()​

public AiResult<InferenceResult> inferFile(String imagePath)
public AiResult<InferenceResult> inferFile(Path imagePath)

按图片文件推理,JPG/PNG/BMP 自动识别。文件不存在即失败,失败读结果里的错误码。

参数:

  • imagePath (String 或 Path) — 图片文件路径

inferImage()​

public AiResult<InferenceResult> inferImage(byte[] imageBytes, ImageDesc desc)
public AiResult<InferenceResult> inferImage(ByteBuffer buf, ImageDesc desc)
public AiResult<InferenceResult> inferImage(BufferedImage img)

内存里已解码的图直接传,裸像素走 inferBuffer。

参数:

  • imageBytes (byte[] 或 ByteBuffer) — 编码字节流或裸像素。BufferedImage 重载传已解码图像
  • desc (ImageDesc) — 图像描述,决定解码口径

示例:

byte[] bytes = Files.readAllBytes(Path.of("photo.jpg"));
AiResult<InferenceResult> r = m.inferImage(bytes, ImageDesc.auto());

inferBuffer()​

public AiResult<InferenceResult> inferBuffer(byte[] pixels, ImageDesc desc)
public AiResult<InferenceResult> inferBuffer(ByteBuffer buf, ImageDesc desc)

裸像素缓冲入口(相机缓冲、内存位图)。宽高与像素格式写进 ImageDesc,格式必须显式指定,禁止 AUTO。

参数:

  • pixels / buf (byte[] / ByteBuffer) — 裸像素,必填
  • desc (ImageDesc) — 宽高与像素格式,必填

cancel()​

public void cancel()

取消正在跑的推理,回执走 AiResult;深层推理会跑完再丢结果,硬截止配合 setTimeout。

示例:

m.cancel();

批量​

逐张排队,失败记日志,不中断整批:

for (String path : files) {
AiResult<InferenceResult> r = ai.inferFile(path);
if (!r.isSuccess()) {
log.add(path + " " + r.getMessage());
continue;
}
}

并发推理​

一个 Model 只绑一个模型路径。

空闲机实测(197,det.onnx,3 轮中位):

  • 单任务基线:1×(约 0.2s)
  • 池 workers=2 双投:两任务同时完成,各约 1–1.5 倍单任务
  • 多实例 2–4 个:总吞吐约等于串行(0.88–0.94×) 并发收益随机器负载变化。

Model 不暴露 weight,多模型设权重走 SessionOptions.weight。

setDeviceWeight()​

public void setDeviceWeight(int gpuDevice, int weight)

运行期改某张卡的接活权重,只影响新进件,不抢在跑任务、不加卡。weight 1–10000 为新权重,0 表示不再接新活;长期分活比例约等于权重占比。

参数:

  • gpuDevice (int) — 卡号
  • weight (int) — 1 到 10000 新权重,0 = 不再接新活

示例:

pool.setDeviceWeight(0, 500);
long t = pool.submit(jpg, ImageDesc.auto(), -1);
String json = pool.wait(t);

submit 的 gpuDevice 传 -1 按权重分活,传具体卡号钉到该卡;DROP_OLDEST 挤掉的任务 wait 报失败。

submit / wait:submit() 投池队列返回 ticket,用 waitFor(ticket) 或 wait(ticket) 取结果。

long ticket = pool.submit(bytes, ImageDesc.auto());
String json = pool.waitFor(ticket);

线程安全:

调用线程安全备注
ModelProbe.probe是只读文件解析,不会建会话
Model 推理入口(inferFile / inferImage / inferBuffer)否单会话互斥,并发走 InferPool
AiDevicePool.submit是可多线程提交,图像字节会被拷走
AiDevicePool.setDeviceWeight是运行期改每卡接活权重,只影响新进件、不抢占、不加卡
AiDevicePool.close否不能和 submit / wait 并发

阈值​

getDefaultThresholds() 返回实例默认表(键为标签名,值为分数下限 [0,1],空表或 null 不过滤)。infer 各入口的 thresholds 参数按标签名只覆盖本次调用。

m.setDefaultThresholds(Map.of("person", 0.5));
AiResult<InferenceResult> r = m.inferFile("photo.jpg", Map.of("person", 0.6));

当前 Core 推理签名没有 per-call 阈值形参,覆盖走默认阈值路径。