推理
对一张图片跑推理,结果输出 JSON。对应 darra_session_infer_image。每次调用处理一张图;相机 / 视频流按帧循环调用。阻塞调用,耗时随 Provider/硬件而定。不承诺硬实时。
功能概览
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 推理 | AiSession.inferImage | String | 方法 | 每次调用处理一张图,结果 JSON。imageBytes 为 AUTO/ENCODED 时是编码文件字节;裸缓冲时是像素内存。desc 不可为 null |
| ImageDesc | format | PixelFormat | 只读 | 图像输入格式。AUTO/ENCODED 时 width/height/stride 忽略(填 0) |
width | int | 只读 | 裸缓冲宽。RGB888/BGR888 时必填(>0) | |
height | int | 只读 | 裸缓冲高。RGB888/BGR888 时必填(>0) | |
stride | int | 只读 | 每行字节数。0 = 紧凑排列(= width×3) | |
auto | ImageDesc | 静态 | 编码字节流,按魔数自嗅探(JPG/PNG/BMP)。裸缓冲禁止用 auto | |
encoded | ImageDesc | 静态 | 显式编码字节流(JPG/PNG/BMP);行为同 auto | |
rgb888 | ImageDesc | 静态 | 裸 RGB888。重载:rgb888(w,h) 紧凑;rgb888(w,h,stride) | |
bgr888 | ImageDesc | 静态 | 裸 BGR888(工业相机常见)。重载同 rgb888 |
Java 绑定的 PixelFormat 与 darra_image_format 逐值对齐,当前暴露:AUTO(0) / ENCODED(1) / RGB888(2) / BGR888(3)。完整枚举见 类型。C 头另有 GRAY8(4) / RGBA8888(5),本绑定未暴露,不要自己填 4/5 绕过工厂。
JNI 桥接会把 size = sizeof(darra_image_desc) 填进 C 结构体首字段,调用方不必手填。本绑定没有批量推理入口,也没有独立的视频流 API。
方法
inferImage(byte[] imageBytes, ImageDesc desc)
public String inferImage(byte[] imageBytes, ImageDesc desc)
每次调用处理一张图,结果输出 JSON。相机 / 视频流按帧循环调用本方法。
参数:
imageBytes(byte[]) — AUTO/ENCODED = 编码文件字节流;裸缓冲 = 像素内存。null =InternalExceptiondesc(ImageDesc) — 见下方工厂。null =InternalException
返回值:
String— envelope JSON。Java 侧拷贝,无需释放
裸缓冲 len 必须 ≥ stride*height(stride 为 0 时按 format 紧凑宽度计:RGB/BGR = width*3)。裸缓冲缺宽高 = InternalException。IoDeniedException = 裸缓冲指针不可读。
同一会话可并发调用(底层运行时会话线程安全;解密明文窗口由 SDK 内部串行管理);吞吐扩展推荐每线程一个会话。close() 禁止与在飞的 inferImage 并发。
示例:
byte[] jpg = java.nio.file.Files.readAllBytes(java.nio.file.Path.of("photo.jpg"));
String json = session.inferImage(jpg, ImageDesc.auto());
工业相机裸缓冲禁止 ImageDesc.auto()(嗅探不出通道序)。stride = 0 表示紧凑排列(= width × 3):
byte[] frame = grabBgrFrame();
String results = session.inferImage(frame, ImageDesc.bgr888(1920, 1080, 0));
连续帧:
for (byte[] frame : cameraFrames()) {
String json = session.inferImage(frame, ImageDesc.bgr888(1920, 1080));
}
相关结构:
{
"schema": 1,
"task": "detect",
"provider": "onnx-cuda",
"elapsedMs": 3.2,
"image": { "width": 1920, "height": 1080 },
"results": [ { "label": "scratch", "score": 0.93, "box": [120, 40, 36, 18] } ]
}
- envelope 字段(schema / task / provider / elapsedMs / image / results)恒定;
results元素随task而变:detect:{label, score, box:[x,y,w,h]}classify:{label, score}top-k 按分降序segment:{label, score, maskRle}- 其余 task 的逐元素 schema 随对应 Provider 落地,本契约只承诺 envelope
- 结果坐标基于
image字段(解码后、送入模型前的尺寸);裸缓冲输入时等于 desc 的宽高 - 永不包含模型明文、密钥等任何敏感字节
task 来自会话元信息,缺席不编 detect。见 元信息 与 元数据。
ImageDesc.auto()
public static ImageDesc auto()
编码字节流,按魔数自嗅探(JPG/PNG/BMP)。对应 PixelFormat.AUTO。裸缓冲禁止用 auto。
返回值:
ImageDesc— format=AUTO,宽高步长为 0
示例:
String json = session.inferImage(jpg, ImageDesc.auto());
ImageDesc.encoded()
public static ImageDesc encoded()
显式声明为已编码字节流(JPG/PNG/BMP)。对应 PixelFormat.ENCODED。行为同 auto()。
返回值:
ImageDesc— format=ENCODED,宽高步长为 0
示例:
String json = session.inferImage(jpg, ImageDesc.encoded());
ImageDesc.rgb888(int width, int height)
public static ImageDesc rgb888(int width, int height)
public static ImageDesc rgb888(int width, int height, int stride)
裸 RGB888。两参数重载 stride=0(紧凑,= width × 3)。宽高 ≤ 0 当场抛 InternalException(「裸缓冲缺宽高」),不把非法 desc 送进 native。
参数:
width(int) — 像素宽,必须 >0height(int) — 像素高,必须 >0stride(int) — 每行字节数;0 = 紧凑(width×3)
返回值:
ImageDesc— format=RGB888
示例:
String json = session.inferImage(pixels, ImageDesc.rgb888(640, 480));
String padded = session.inferImage(pixels, ImageDesc.rgb888(640, 480, 1920));
ImageDesc.bgr888(int width, int height)
public static ImageDesc bgr888(int width, int height)
public static ImageDesc bgr888(int width, int height, int stride)
裸 BGR888(工业相机常见)。重载与约束同 rgb888。
参数:
width(int) — 像素宽,必须 >0height(int) — 像素高,必须 >0stride(int) — 每行字节数;0 = 紧凑(width×3)
返回值:
ImageDesc— format=BGR888
示例:
String json = session.inferImage(frame, ImageDesc.bgr888(1920, 1080, 0));
只读访问:format() / width() / height() / stride()。format() 类型见 PixelFormat。
完整示例
场景:一台刚装完系统的客户机。目标:装齐环境 → 打开加密模型 → 读元信息 → 推理一张编码图 → 再按帧循环裸缓冲 → 干净退出。
import xyz.darra.ai.*;
import java.nio.file.Files;
import java.nio.file.Path;
public class InferExample {
public static void main(String[] args) throws Exception {
System.err.println(AiRuntime.versionString());
AiRuntime.ensure(null, null, (percent, stage) ->
System.out.printf("\r环境准备 [%-8s] %5.1f%%", stage, percent));
System.out.println();
try (AiSession session = AiSession.open(
"model.darmodel", "model.darmkey", null, null)) {
System.out.println("[meta] " + session.metaJson());
byte[] image = Files.readAllBytes(Path.of("photo.jpg"));
String results = session.inferImage(image, ImageDesc.auto());
System.out.println("[results] " + results);
for (byte[] frame : cameraFrames()) {
String json = session.inferImage(frame, ImageDesc.bgr888(1920, 1080));
System.out.println(json);
}
} catch (AiException ex) {
System.err.println("[" + ex.getCode() + "] " + ex.getMessage());
System.err.println("建议: " + ex.getHint());
System.exit(ex.getCode());
}
}
}
要点:
- ABI 核对先行(
NativeLoader加载时已核 major == 1),装错库不往下走; ensure幂等——已装好就是秒过,可每次启动都调;- Java 侧字符串无需
darra_string_free; - 每次调用一张图,循环帧即可接相机;
- 任何一步失败,
getHint()就是给最终用户的修复建议(见 错误处理)。