为 Electron 创建 WinML 加载项

本指南介绍如何在 Electron 应用中创建使用 Windows Machine Learning(WinML)的 C# 本机加载项。 使用 WinML,可以在 Windows 设备上本地运行machine learning模型(ONNX 格式),以便执行图像分类、对象检测等任务。

先决条件

注释

WinML 在任何Windows 10(1809+)或Windows 11设备上运行。 为了获得最佳性能,建议使用 GPU 或 NPU 的设备,但 API 也适用于 CPU。

步骤 1:创建 C# 本机加载项

npx winapp node create-addon --template cs --name winMlAddon

这会创建一个 winMlAddon/ 文件夹,其中 C# 项目配置有 Windows SDK 和 Windows App SDK 引用。

生成加载项:

npm run build-winMlAddon

步骤 2:下载 SqueezeNet 模型

  1. 安装 AI 开发画廊
  2. 导航到 分类图像示例
  3. 下载 SqueezeNet 1.1 模型
  4. .onnx 文件复制到 project 根目录中的 models/ 文件夹中

步骤 3:添加所需的 NuGet 包

更新项目根目录中的 Directory.packages.props

<PackageVersion Include="Microsoft.ML.OnnxRuntime.Extensions" Version="0.14.0" />
<PackageVersion Include="System.Drawing.Common" Version="9.0.9" />

更新 winMlAddon/winMlAddon.csproj 以添加包引用:

<PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions" />
<PackageReference Include="System.Drawing.Common" />

步骤 4:添加示例代码

AI 开发画廊提供 SqueezeNet 图像分类的完整实现。 可以在 electron-winml 示例中找到改编的代码

winMlAddon/从示例复制文件夹,或使用示例代码手动更新winMlAddon/addon.cs

关键实现详细信息

Project根路径:加载项要求 JavaScript 代码传递project根路径,以便找到 ONNX 模型和本机依赖项。

预加载本机依赖项:插件包含一种用于加载开发和生产环境所需的 DLL 的方法。

Electron Forge 配置:将打包工具配置为解压缩本地文件:

module.exports = {
  packagerConfig: {
    asar: {
      unpack: "**/*.{dll,exe,node,onnx}"
    },
    ignore: [
      /^\/.winapp\//,
      "\\.msix$",
      /^\/winMlAddon\/(?!dist).+/
    ]
  },
};

步骤 5:生成加载项

npm run build-winMlAddon

步骤 6:测试加载项

打开 src/index.js 并加载该加载项:

const winMlAddon = require('../winMlAddon/dist/winMlAddon.node');

添加测试函数:

const testWinML = async () => {
  try {
    let projectRoot = path.join(__dirname, '..');
    if (projectRoot.includes('app.asar')) {
      projectRoot = projectRoot.replace('app.asar', 'app.asar.unpacked');
    }

    const addon = await winMlAddon.Addon.createAsync(projectRoot);
    console.log('Model loaded successfully!');

    const imagePath = path.join(projectRoot, 'test-images', 'sample.jpg');
    const predictions = await addon.classifyImage(imagePath);

    console.log('Top predictions:');
    predictions.slice(0, 5).forEach((pred, i) => {
      console.log(`${i + 1}. ${pred.label}: ${(pred.confidence * 100).toFixed(2)}%`);
    });
  } catch (error) {
    console.error('Error testing WinML:', error.message);
  }
};

通过创建 test-images/ 包含示例映像的文件夹来准备测试映像,然后运行:

npm start

步骤 7:更新调试标识

npx winapp node add-electron-debug-identity

注释

已知 Windows 的一个 bug 会导致稀疏打包的 Electron 应用程序崩溃或显示空白窗口。 有关解决方法,请参阅 安装指南

后续步骤