跳到主要内容

推理

对一张图片跑推理,结果输出 JSON。对应 darra_session_infer_image。每次调用处理一张图;相机 / 视频流按帧循环调用。阻塞调用,耗时随 Provider/硬件而定。不承诺硬实时。

功能概览

类别属性类型访问说明
推理AiSession.inferImageString方法每次调用处理一张图,结果 JSON。imageBytes 为 AUTO/ENCODED 时是编码文件字节;裸缓冲时是像素内存。desc 不可为 null
ImageDescformatPixelFormat只读图像输入格式。AUTO/ENCODED 时 width/height/stride 忽略(填 0)
widthint只读裸缓冲宽。RGB888/BGR888 时必填(>0)
heightint只读裸缓冲高。RGB888/BGR888 时必填(>0)
strideint只读每行字节数。0 = 紧凑排列(= width×3)
autoImageDesc静态编码字节流,按魔数自嗅探(JPG/PNG/BMP)。裸缓冲禁止用 auto
encodedImageDesc静态显式编码字节流(JPG/PNG/BMP);行为同 auto
rgb888ImageDesc静态裸 RGB888。重载:rgb888(w,h) 紧凑;rgb888(w,h,stride)
bgr888ImageDesc静态裸 BGR888(工业相机常见)。重载同 rgb888

Java 绑定的 PixelFormatdarra_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 = InternalException
  • desc (ImageDesc) — 见下方工厂。null = InternalException

返回值:

  • String — envelope JSON。Java 侧拷贝,无需释放

裸缓冲 len 必须 ≥ stride*height(stride 为 0 时按 format 紧凑宽度计:RGB/BGR = width*3)。裸缓冲缺宽高 = InternalExceptionIoDeniedException = 裸缓冲指针不可读。

同一会话可并发调用(底层运行时会话线程安全;解密明文窗口由 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) — 像素宽,必须 >0
  • height (int) — 像素高,必须 >0
  • stride (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) — 像素宽,必须 >0
  • height (int) — 像素高,必须 >0
  • stride (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());
}
}
}

要点:

  1. ABI 核对先行NativeLoader 加载时已核 major == 1),装错库不往下走;
  2. ensure 幂等——已装好就是秒过,可每次启动都调;
  3. Java 侧字符串无需 darra_string_free
  4. 每次调用一张图,循环帧即可接相机;
  5. 任何一步失败,getHint() 就是给最终用户的修复建议(见 错误处理)。