Exports the ONNX file to a WebNN JavaScript file and a bin file containing the weights.
This project is derived from onnx2json.
$ pip install -U onnx protobuf numpyusage: onnx2webnn.py [-h] -if INPUT_ONNX_FILE_PATH -oj OUTPUT_JS_PATH [-nhwc] [-json]
[-i JSON_INDENT] [-imagenet] [-segmentation]
options:
-h, --help show this help message and exit
-if INPUT_ONNX_FILE_PATH, --input_onnx_file_path INPUT_ONNX_FILE_PATH
Input ONNX model path. (*.onnx)
-oj OUTPUT_JS_PATH, --output_js_path OUTPUT_JS_PATH
Output WebNN JavaScript file path (*.js)
-nhwc, --nhwc Generate WebNN operators taking nhwc input layout, including conv2d, convTranspose2d, resample2d and pool2d
-json, --dump_json Dump the JSON representation of ONNX model
-i JSON_INDENT, --json_indent JSON_INDENT
Number of indentations in JSON. (default=2)
-imagenet, --imagenet
Test imagenet model in the generated index.html
-segmentation, --segmentation
Test segmentation model in the generated index.html
Note: Before using this tool, please ensure override the free dimensions of input ONNX model by using onnxruntime_perf_test tool, for example
$ onnxruntime_perf_test -I -r 1 -u mobilenetv2-12-static.onnx -f batch_size:1 -o 1 mobilenetv2-12.onnxMake a folder "mobilenet" that will contain the generated files:
$ mkdir mobilenetThen run the following command to create WebNN JavaScript model for the static ONNX model:
$ python onnx2webnn.py -if ../sample_models/mobilenetv2-12-static.onnx -oj mobilenet/mobilenet.jsIt will generate "mobilenet.bin" and "mobilenet.js" besides "mobilenet.json" in "mobilenet" folder.
An "index.html" is also generated for testing the WebNN model.
Start a node.js http-server in the folder containing generated model files and launch a web browser with URL http://localhost:8080/.
$ http-serverThe default input layout of ONNX model is NCHW, however some WebNN backends prefer to NHWC input layout, such as TFLite for CPU and GPU. For those backends, using WebNN NHWC model may have better performance.
To generate the NHWC WebNN model from an ONNX model, add the "--nhwc" switch, such as
$ python onnx2webnn.py -if ../sample_models/mobilenetv2-12-static.onnx -oj mobilenet_nhwc/mobilenet_nhwc.js -nhwcWebNN API exposes the backend preferred layout via MLContext.opSupportLimit().preferredInputLayout, a web app can load the corresponding WebNN model based on the preferred layout. For example, in JavaScript code
const deviceType = 'gpu'; // or 'cpu', 'npu'
const context = await navigator.ml.createContext({deviceType});
const layout = context.opSupportLimits().preferredInputLayout;
let webnnModel;
if (layout == 'nhwc') {
webnnModel = new MobilenetNhwc();
} else {
webnnModel = new Mobilenet();
}
// Load the weights in preferred layout and build the graph.
await webnnModel.build({deviceType});
// Do inference with webnnModel.run()This tool supports converting QDQ (Quantize-Dequantize) ONNX model to WebNN model. According WebNN quantizeLinear and dequantizeLinear spec, it may need to reshape the scale and zero point tensor according to the rank of input tensor and axis. To support this feature, please ensure the ONNX model has shape info for each output tensor by running onnx-simplifier, e.g.
> pip3 install onnxsim
> onnxsim ../sample_models/mobilenetv2-12-qdq-static.onnx ../sample_models/mobilenetv2-12-qdq-static-simplified.onnxAfter that, generate WebNN model with the following command line
> python onnx2webnn.py -if ../sample_models/mobilenetv2-12-qdq-static-simplified.onnx -oj mobilenet_qdq/mobilenet_qdq.jsFor NHWC model, use
> python onnx2webnn.py -if ../sample_models/mobilenetv2-12-qdq-static-simplified.onnx -oj mobilenet_qdq_nhwc/mobilenet_qdq_nhwc.js -nhwcSome models contain nodes that need to know the shape info before conversion. For example squeezenet1.1-7.onnx, it contains Concat operator with axis -1. To handle it, please ensure the ONNX model has shape info for each output tensor by running onnx-simplifier, e.g.
> pip3 install onnxsim
> onnxsim ../sample_models/squeezenet1.1-7.onnx ../sample_models/squeezenet1.1-7-simplified.onnxAfter that, generate WebNN model from the simplified ONNX model with the following command line
> python onnx2webnn.py -if ../sample_models/squeezenet1.1-7-simplified.onnx -oj squeezenet/squeezenet.jsModels trained by ImageNet for image classification, such as MobileNet, can be tested with index.html generated with --imagenet switch. This is uesful to verify the correctness of generated WebNN models.
For example
$ python onnx2webnn.py -if ../sample_models/mobilenetv2-12-static.onnx -oj mobilenet/mobilenet.js -imagenetIt will generate image pre-processing and result post-processing code in index.html. After launching index.html, you can upload an image as input. After running the model, the top 5 classification results will be displayed.
For image segmetnation models, such as MediaPipe selfie segmentation model, you can specify --segmentation switch to generate the testing code in index.html. This is useful to verify the correctness of generated WebNN models.
For example, download MediaPipe selfie segmentation ONNX model from https://huggingface.co/onnx-community/mediapipe_selfie_segmentation/blob/main/onnx/model.onnx, rename it to mediapipe-selfie-segmentation.onnx.
Use onnx2sim to override the free dimension and do the shape inference:
$ onnxsim mediapipe-selfie-segmentation.onnx mediapipe-selfie-segmentation-simplified.onnx --overwrite-input-shape 1,3,256,256Generate the WebNN model with test code
$ python onnx2webnn.py -if ..\sample_models\mediapipe-selfie-segmentation-simplified.onnx -oj selfie_segmentation_nhwc\selfie_segmentation_nhwc.js -nhwc -segmentationIt will generate image pre-processing and result post-processing code in index.html. After launching index.html, you can upload an image as input. After running the model, the original image, mask and masked image will be displayed.
You can also dump the JSON file for debugging purpose.
$ python onnx2webnn.py -if ../sample_models/mobilenetv2-12-static.onnx -oj mobilenet/mobilenet.js -json