feat(inference): support direct ONNX inpainting models#1159
Conversation
REQUEST_CHANGES — independent reviewer verdictPR: #1159 Delivery status: posting was attempted as reviewer identity Blocking findings
Independent evidence and passed gates
Ownership routing
|
REQUEST_CHANGES — independent reviewer re-reviewPR: #1159 Blocking finding
Prior REQUEST_CHANGES dispositionAll five prior findings are independently verified fixed at the reviewed head:
Independent evidence
This is a single freshness blocker only. Re-review is required after the rebase and refreshed baseline evidence. |
7859d8e to
28815d6
Compare
|
The stale-baseline request has been addressed without changing the committed scope or Goal ceiling. The branch is rebased onto current The replacement charter, recipe-free baseline, both required CPU fp32/fp16 build and perf tuples, supplementary ONNX-reference comparison, eval blockers, analyze summaries, and five quality checks were refreshed against that exact head/base pair. The PR description now transcribes those owning artifacts, including the new baseline/per-tuple values and portable reproduction commands. The PR remains Draft with |
|
The explainer-owned PR prose has been refreshed for repaired head
The PR remains Draft with |
|
Both final-r4 blockers have been addressed at current head
The PR description has been refreshed from producer-r5/tester-r5, replacement charter r2, and learner-r2. Concrete build/perf/runtime/eval values remain unchanged only where tester r5 explicitly validated carryover. The PR remains Draft with |
Summary
This adds generic direct-ONNX LaMa inpainting support for
opencv/inpainting_lama, including bare Hugging Face repository resolution, an explicit persisted image+mask runtime contract, and CPU recipes for fp32 and fp16. The contribution ships at Effort/Outcome L2 and reaches the committed Goal ceiling of L1 PASS for both required CPU tuples. The published graph is already INT8-prequantized, so “fp32” and “fp16” identify the precision of its remaining floating initializers rather than pure-float models.Model metadata
What the model does
LaMa performs image inpainting: it accepts a 512 x 512 RGB image and a 512 x 512 single-channel binary mask, synthesizes replacement RGB content for the masked region, and returns an inpainted 512 x 512 RGB image (verified).
Evidence: the model card pinned to revision
aee6d22f0a13e5e35af1c9a1c3afd62841fc6f3f, pinnedlama.pyLama.infer()wrapper, and published ONNXimage,mask, andoutputcontract.Primary user stories
Supported tasks
config.json,pipeline_tag, Transformers class, or Optimum registration; no such surface is claimed.Model architecture
lama.pyand published ONNX graph scopes, I/O, and topology (mapped).Validation and support evidence
Baseline
The replacement charter freezes WinML
winml, version 0.2.0at currentmaincommit4daf0f19097d03e92aeb3c4f9713b7d037e0be3d. The repaired feature head isf03add820f384ce725e83400d53d108ff43aad0a, based directly on that commit; tester r5 refreshed revision, semantic-contract, analyze, component/op, and quality evidence at this head and retained earlier build/perf/eval measurements only where artifact-integrity and affected-scope checks established valid carryover.The baseline below is intentionally run in a detached clean worktree at the frozen current-main SHA. It distinguishes the canonical bare repository-ID failure from the successful direct-ONNX diagnostic; the direct-file result proves generic graph ingestion/execution only and does not upgrade bare-ID support on current
main.config.jsonmodel_type, so currentmainreportsUnrecognized model in opencv/inpainting_lama.winml configgenerated a recipe withskip_optimize: true,export: null, emptyoptim,quant: null,compile: null, and loader taskinpainting; it had no runtime contract. The diagnostic direct-ONNX build above succeeded and preserved the published 92,591,623-byte graph, but this does not upgrade the failing bare-repository workflow.w8a8because the published graph is prequantized.inpaintingis unsupported bywinml eval. The pinnedmattmdjaga/human_parsing_datasetrevisiondb120bb5c18c146a8fbd2160f7575a288269fe7dtrain sample is schema-probe-only; it has no authoritative image+mask+restored-target inpainting metric, and no metric validity is claimed.Goal
mainmoved from38767add6f91c7b10b6394fae3af6f437e02effdto4daf0f19097d03e92aeb3c4f9713b7d037e0be3d; the Effort, Goal ceiling, Outcome, and success definition did not change.Outcome
examples/recipes/opencv_inpainting_lama/cpu/cpu/inpainting_fp32_config.jsonandexamples/recipes/opencv_inpainting_lama/cpu/cpu/inpainting_fp16_config.json.inpainting_lama_2025jan.onnxartifact and recording the repository ID, selected artifact, and immutable Hub revision in the build manifest.inpaintingcaller contract is canonical: nonzero mask pixels identify holes (the replaced region). Persistedruntime.options.mask_semanticsdoes not redefine caller input; it declares the model-side ONNX mask tensor polarity. After binarizing the caller mask, the adapter preserves it fornonzero-is-hole(hole → 1, background → 0) and inverts it forzero-is-hole(hole → 0, background → 1), preserving the same semantic hole region.[[0,1],[1,1],[1,2]]; the focused semantic-contract regressions passed 3 tests, the complete task/inpainting files passed 28 tests, and the broader affected suite passed 369 tests.lama-001throughlama-004,_task-inpainting-001, and_meta-085through_meta-088without adding, retiring, or rewriting finding IDs. The inpainting-eval gap remains tracked by microsoft/winml-cli#1158; skill-only evidence remains isolated in Draft PR gim-home/ModelKitArtifacts#170.The L1 ceiling remains the formal result. Supplementary L2 used the published ONNX artifact at revision
aee6d22f0a13e5e35af1c9a1c3afd62841fc6f3fbecause the checkpoint publishes no PyTorch weights or loadable PyTorch implementation; no PyTorch result is fabricated.The public runtime adapter exactly matched direct candidate output for both tuples: fp32 cosine 0.9999999999999999, max abs 0.0; fp16 cosine 1.0, max abs 0.0. Against the pinned source ONNX through that adapter, fp32 remained exact and fp16 measured cosine 0.9847192758836978, max abs 135.0, mean abs 9.529802958170572, and RMSE 28.638184333305173.
Quality results
Tester r5 validated the current head
f03add820f384ce725e83400d53d108ff43aad0a. Build/artifact, CLI perf, semantic runtime perf, supplementary ONNX-reference, and eval evidence was retained only under the tester's explicit carryover checks; semantic-contract, analyze, component/op, quality, and provenance evidence was freshly rerun or refreshed.mypy -p winml.modelkitgit diff --check origin/main...HEADThe current repair changed public contract documentation/error wording and focused tests, not
_prepare_mask()executable conversion, recipes, model artifacts, perf/session code, or eval support. Tester r5 reverified source/recipe/artifact hashes and affected scope before retaining the concrete build, perf, runtime, ONNX-reference, and eval evidence below.Per-EP/device/precision results — including perf and eval data
Goal ladder
InferenceEngine→ persisted manifest contract →WinMLInpaintingPipeline→ CPU model → PNG postprocessing, with exact adapter/direct parity.Build and CLI perf
CLI perf used 3 warmups and 20 measured iterations with the same named semantic inputs.
Both artifacts retain the source graph’s 598 INT8 initializers. The coarse CLI precision detector consequently reports
w8a8; tuple identity is established by requested precision plus the audited residual FLOAT→FLOAT16 transition.Supplementary public-runtime measurements used 2 warmups and 5 measured iterations:
Eval support evidence
mattmdjaga/human_parsing_dataset/db120bb5c18c146a8fbd2160f7575a288269fe7d/ noneTask 'inpainting' is not supported; no output was produced. Schema probe exit 2 has the same unsupported-task registry gap.mattmdjaga/human_parsing_dataset/db120bb5c18c146a8fbd2160f7575a288269fe7d/ noneTask 'inpainting' is not supported; no output was produced. Schema probe exit 2 has the same unsupported-task registry gap.The dataset is a schema probe only and does not establish an authoritative restored-target contract or canonical inpainting metric. This is an evaluator-registry plus metric-dataset-contract gap, not an EP, export, precision, build, or runtime failure.
Delta
Recipes and configuration
Relative to the replacement charter’s generated baseline recipe, both checked-in recipes add the explicit
/runtimecontract; fp16 additionally changes/quantfromnullto an explicit FP16 conversion configuration./runtimenull{"pipeline":"inpainting","options":{"image_input_name":"image","mask_input_name":"mask","output_name":"output","image_color_order":"bgr","image_value_range":[0,1],"mask_semantics":"nonzero-is-hole","output_color_order":"bgr","output_value_range":[0,255]}}/quantnullmode: fp16configuration below{ "mode": "fp16", "samples": 10, "calibration_method": "minmax", "weight_type": "uint8", "activation_type": "uint8", "per_channel": false, "symmetric": false, "weight_symmetric": null, "activation_symmetric": null, "save_calibration": false, "distribution": "uniform", "seed": null, "calibration_load_path": null, "calibration_save_path": null, "op_types_to_quantize": null, "nodes_to_exclude": null, "fp16_keep_io_types": true, "fp16_op_block_list": null }The public task schema defines one caller-side convention: nonzero mask pixels are holes. The persisted runtime contract separately declares exact image/mask/output tensor roles, BGR image
[0,1], model-side ONNX mask tensor polarity, and BGR output[0,255]. For the checked-in LaMa recipes,mask_semantics: "nonzero-is-hole"means the canonical caller mask is passed through after binarization. A different model declaringzero-is-holereceives the inverted ONNX tensor while the caller-designated hole region remains unchanged. Both schemas validated, actual builds persisted the contract in resolved configuration and manifests, and reducibility is consistent with the charter. The fp32 recipe has no additional delta; the fp16 recipe converts only the remaining floating tensors while preserving prequantized INT8 weights. The production recipe README remains unchanged.The actual public pipeline passed all four fail-closed contract checks: missing contract, unsupported image range, absent/non-distinct tensor roles, and an unknown model-specific option all raised their expected
ValueErrorrather than guessing semantics.Code
src/winml/modelkit/loader/onnx_hub.pyResolvedHubOnnx,resolve_hf_repo_onnx()src/winml/modelkit/utils/model_input.pyModelInput,resolve_model_input()src/winml/modelkit/commands/build.pybuild(),_run_quantize_stage(),_build_onnx_pipeline()src/winml/modelkit/config/build.pyWinMLRuntimeConfig,WinMLBuildConfig,generate_onnx_build_config()src/winml/modelkit/build/common.pyensure_pre_quantized_stamped()mode=fp16.src/winml/modelkit/build/onnx.pybuild_onnx_model()src/winml/modelkit/build/hf.pybuild_hf_model()src/winml/modelkit/utils/cli.pynormalize_model_arg()src/winml/modelkit/models/auto.pyWinMLAutoModel.from_pretrained()src/winml/modelkit/inference/engine.pyInferenceEngine.load(),InferenceEngine.load_schema_only()src/winml/modelkit/inference/tasks.pyTASK_REGISTRY,_postprocess_inpainting()src/winml/modelkit/inference/pipeline.py_CUSTOM_PIPELINE_FACTORIES,create_pipeline()src/winml/modelkit/inference/inpainting.pyWinMLInpaintingPipeline,_prepare_mask()src/winml/modelkit/utils/manifest.pyWinMLManifestsrc/winml/modelkit/models/winml/base.pyWinMLPreTrainedModel.runtime_configThe committed diff also adds or updates focused tests for build paths, config generation, inference, task registration, Hub resolution, auto-model loading, manifests, and model-input resolution.
Analyze summary — component level and op level
ANALYZE-PARTIAL-SUCCESS: both literal tester-owned
analyze --ep all --device allprocesses exited 1 because OpenVINO plugin registration failed with Error 126 (onnxruntime_providers_shared.dllwas missing). Each process nevertheless emitted complete fail-closed JSON with 11 unique nonempty classification rows, including all six required public rule-backed targets, complete graph metadata, and 100% component mapping. This is static rule analysis, not runtime execution; every emitted EP row hasruntime_support=false.Component-level summary
There are no component-mapping gaps. The nonzero process exits are retained; complete component/op payloads do not establish runtime compatibility.
Op-level summary
Reproduce commands
The block starts with tester-owned portable build/perf/eval commands. The rules setup downloads the official
v0.2.0release asset verified through the public GitHub release API: assetrules-v0.2.0.zip, published SHA-2566dcabbe7f5493fbc2bd23de195ab6e35b3578d510f18c2e220bc5538a1f232cc, six expected EP directories, and 1,746 Parquet files. The pinned package expands those EP directories directly at the selected root, soWINMLCLI_RULES_DIRis set deterministically to that resolved expansion path. The two tester-owned analyze invocations include literal--ep all --device all; on the tester host each exited 1 for the OpenVINO Error 126 above while still emitting the complete 11-row static payload.