Wasmtime 中基于 wasi-nn 与 WinML 的图像分类示例:fixture 模型、图像与标签文件的准备与使用
2026/9/21 18:14:19 网站建设 项目流程

Wasmtime 中基于 wasi-nn 与 WinML 的图像分类示例:fixture 模型、图像与标签文件的准备与使用

【免费下载链接】wasmtimeA lightweight WebAssembly runtime that is fast, secure, and standards-compliant项目地址: https://gitcode.com/gh_mirrors/wa/wasmtime

导读

本文围绕 Wasmtime 仓库中crates/wasi-nn/examples/classification-example-winml示例的 fixture 资源目录(fixture/README.md)展开,说明该目录下三份核心素材——ONNX 分类模型、ImageNet 标签文件与测试图像——的来源、许可证及其在完整推理链路中的具体作用。读者将掌握:如何理解并复用这套 fixture 素材、如何在 Windows 上以 WinML 为后端把 wasi-nn 示例从编译一路跑到输出 Top-5 分类结果,以及如何替换为自己的模型与图片。

一、fixture 目录是什么:一份推理示例的“素材清单”

crates/wasi-nn/examples/classification-example-winml/fixture/是 WinML 分类示例的输入资源目录,目录内除 README.md 外,还包含三个被示例代码直接引用的文件:

文件作用来源许可证
mobilenet.onnx用于推理的 MobileNetV2-7 图像分类 ONNX 模型下载自 ONNX 官方模型库(onnx/models 仓库的validated/vision/classification/mobilenet路径)onnx/models 仓库 LICENSE
synset.txtImageNet 分类标签文件(共 1000 行,格式为类别ID 标签文本同样下载自 onnx/models 仓库的validated/vision/classification路径onnx/models 仓库 LICENSE
kitten.png224×224 的测试输入图像下载自 onnxruntime 官方仓库 WinML 测试图片目录onnxruntime 仓库 LICENSE

fixture 的 README 本质上是一份素材溯源清单:它明确记录了每个文件的下载来源与许可证归属,保证示例可复现、可合规分发。在替换素材时,这份清单也提醒使用者关注第三方模型与数据的授权边界。

说明:以上来源信息以 fixture/README.md 中的记载为准,本文不再重复给出外部链接;如需二次分发或商用,请自行核对 onnx/models 与 onnxruntime 仓库的许可证原文。

二、三份素材在推理流程中的分工(结合 main.rs)

示例程序 src/main.rs 的完整链路依次使用这三份素材:

  1. 模型加载wasi_nn::GraphBuilder::new(wasi_nn::GraphEncoding::Onnx, wasi_nn::ExecutionTarget::CPU)创建图构建器,通过build_from_files(["fixture/mobilenet.onnx"])从文件构建计算图,再init_execution_context()得到执行上下文。
  2. 图像读取与预处理fs::read("fixture/kitten.png")读入原始图像字节,随后交给preprocess函数(见下方说明),输出符合模型输入要求的张量。
  3. 输入张量设置context.set_input(0, wasi_nn::TensorType::F32, &[1, 3, 224, 224], &tensor_data)指定输入索引 0、数据类型 F32、形状 NCHW 为[1, 3, 224, 224](1 张图、RGB 三通道、224×224 分辨率)。
  4. 推理执行context.compute()触发 WinML 后端评估,代码会打印耗时毫秒数。
  5. 输出读取get_output(0, &mut output_buffer[..])读取形状为[1, 1000, 1, 1]的原始 logits(对应 ImageNet 1000 类)。
  6. 标签解析:读取fixture/synset.txt,按行拆分并取第二列及之后的文本作为可读标签(例如n01440764 tench, Tinca tinca解析为tench, Tinca tinca),最终通过sort_results按概率降序输出 Top-5 结果。

图像预处理的关键参数(来自模型规范)

preprocess函数实现了 MobileNet 官方要求的预处理流程:

let tensor_data = preprocess( image_data.as_slice(), 224, 224, &[0.485, 0.456, 0.406], // mean,ImageNet 标准均值 &[0.229, 0.224, 0.225], // std,ImageNet 标准标准差 );

具体步骤为:image::load_from_memory解码图像 →resize_exact(224, 224, Triangle)双线性(三角滤波)缩放 →to_rgb8()转 RGB → 逐像素执行(pixel / 255.0 - mean[channel]) / std[channel]归一化 → 按to_ne_bytes()拆成字节写入以[1, 3, 224, 224]布局的Vec<u8>注意:图像尺寸、均值/标准差必须与模型训练时一致,否则分类精度会显著下降。

后处理:softmax 与 Top-5 排序

postprocess先对[1, 1000, 1, 1]的原始输出做 softmax(指数化后按类别轴归一),sort_results再把概率与synset.txt标签一一对应并按概率降序排序,最后打印前 5 项:

println!("Found results, sorted top 5: {:?}", &sort_results(&result, &labels)[..5]);

三、端到端运行:从构建 Wasmtime 到输出分类结果

fixture 素材只有在完整示例中才有意义。按照示例目录 README.md 的说明,在Windows 10 v1803 及以上环境按以下步骤运行:

  1. winml特性构建 Wasmtime(在 Wasmtime 仓库顶层目录执行):

    cargo build --release --features wasmtime-wasi-nn/winml

    winml特性在 crates/wasi-nn/Cargo.toml 中定义(winml = ["dep:windows"]),且属于默认特性组合default = ["openvino", "winml"]的一部分;它引入了windowscrate,使 wasi-nn 可以调用 Windows 的 WinML 机器学习 API。

  2. 切换到示例目录(Wasmtime 顶层记为%PROJECT_DIR%):

    set PROJECT_DIR=%CD% cd crates\wasi-nn\examples\classification-example-winml
  3. 安装wasm32-wasip1Rust 目标(示例编译为 WebAssembly,无法用宿主目标编译):

    rustup target add wasm32-wasip1
  4. 编译示例,产物是.wasm文件:

    cargo build --release --target=wasm32-wasip1

    该 crate 依赖(见 Cargo.toml)为wasi-nn = "0.6.0"image(启用png特性)与ndarray;Cargo.toml 中通过独立的[workspace]声明将其排除在 Wasmtime 主工作区之外,避免与宿主构建互相干扰。

  5. 运行示例,关键是把fixture目录映射进 WebAssembly 可见的文件空间:

    %PROJECT_DIR%\target\release\wasmtime.exe --dir fixture::fixture -S nn target\wasm32-wasip1\release\wasi-nn-example-winml.wasm
    • --dir fixture::fixture:将宿主侧的fixture目录以同名路径暴露给 guest,使build_from_files(["fixture/mobilenet.onnx"])fs::read("fixture/kitten.png")等路径可解析;
    • -S nn:开启 wasi-nn 相关的能力开关,允许 guest 调用神经网络推理接口。
  6. 观察输出:程序依次打印“Created an execution context.”、输入张量字节数、推理耗时,最后给出按概率排序的 Top-5 分类结果。

替换模型或图像时的注意事项

示例 README 明确指出:如需换用其他图片或 ONNX 模型,只需修改fixture目录中的文件,并同步调整 src/main.rs 中可能受影响的路径。替换时还需留意:

  • 新模型若输入不是 224×224,需同步修改preprocess的目标尺寸与set_input的形状;
  • 新模型的类别数若不为 1000,需同步调整输出缓冲区大小与synset.txt(或等价标签文件)的行数;
  • 归一化均值/标准差以模型文档为准,MobileNet 使用 ImageNet 的[0.485, 0.456, 0.406]/[0.229, 0.224, 0.225]

四、fixture 素材背后的 WinML 后端实现

示例之所以能在 Windows 上直接运行 ONNX 模型,靠的是 wasi-nn 的 WinML 后端 crates/wasi-nn/src/backend/winml.rs。从源码结构看,整个调用链可以概括为:

  • WinMLBackend::load:要求恰好一个模型构建器(builders.len() != 1时报InvalidNumberOfBuilders),将 ONNX 字节写入InMemoryRandomAccessStream,通过LearningModel::LoadFromStream加载模型;ExecutionTarget::Cpu映射为LearningModelDeviceKind::CpuExecutionTarget::Gpu映射为DirectX,而Tpu目前是unimplemented!()
  • init_execution_context:用LearningModelDevice::Create创建设备、LearningModelSession::CreateFromModelOnDevice建立会话,封装为执行上下文。
  • set_input/compute/get_output:按索引或名称在模型的InputFeatures/OutputFeatures中定位张量,经to_inspectable(wasi-nn 张量 → WinMLIInspectable)与to_tensor(反向转换)完成数据搬运,最后调用session.Evaluate执行推理。
  • 张量类型支持to_inspectable支持 Fp32(TensorFloat)、I64(TensorInt64Bit)以及以 f32 数组包装的 Fp16(TensorFloat16Bit),并做对齐校验;to_tensor反向支持 Float16、Float、Int64 三种TensorKind。该文件内还包含 fp16 / fp32 / i64 三组单元测试,用于验证 wasi-nn 与 WinML 之间的往返转换(winml.rs)。

换言之,guest 侧wasi-nn的 API 调用在宿主侧被翻译为 WinML 的LearningModel/LearningModelSession/LearningModelBinding操作,而mobilenet.onnx正是被LearningModel::LoadFromStream加载的那个字节流。

五、fixture 与 CI 测试

示例目录的父级 examples/README.md 提到:CI 通过ci/run-wasi-nn-example.sh测试分类示例。这说明fixture中的三份素材不仅是本地演示输入,也承担了自动化回归验证的职责——模型加载、预处理、推理与 Top-5 排序整条链路都会被持续检验,从而保证 wasi-nn API 与各后端实现(含 WinML)的行为稳定。

小结

crates/wasi-nn/examples/classification-example-winml/fixture/目录虽小,却承载了 WinML 分类示例的全部输入:ONNX 模型决定“能算什么”,synset 标签决定“结果叫什么”,测试图像决定“算的是什么”。理解这份素材清单的来源、许可证与格式约束,再结合示例 README 的构建运行步骤与 winml.rs 的后端实现,即可在 Windows 上完整复现 wasi-nn + WinML 的图像分类流程,并自如地将模型、图片替换为自有资产。

【免费下载链接】wasmtimeA lightweight WebAssembly runtime that is fast, secure, and standards-compliant项目地址: https://gitcode.com/gh_mirrors/wa/wasmtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询