Download predict_onnx.py from bxding/RC1: direct link, hf CLI and curl.
- Browser
- Download file 3.87 kB
-
https://huggingface.co/bxding/RC1/resolve/main/predict_onnx.py
- Command line
-
hf download hf://bxding/RC1/predict_onnx.py
-
curl -L -o predict_onnx.py https://huggingface.co/bxding/RC1/resolve/main/predict_onnx.py
3.87 kB
| """Predict with an exported ONNX model. Needs only onnxruntime, numpy, and Pillow (no PyTorch). | |
| python predict_onnx.py --model grid9.int8.onnx --image challenge.png --target bicycles | |
| """ | |
| import argparse | |
| import json | |
| from pathlib import Path | |
| import numpy as np | |
| import onnxruntime as ort | |
| from PIL import Image | |
| from targets import target_name | |
| MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32) | |
| STD = np.array([0.229, 0.224, 0.225], dtype=np.float32) | |
| IMAGE_NAMES = ("image.jpg", "image.jpeg", "image.png", "image.webp") | |
| def preprocess(image, size): | |
| """Matches torchvision Resize (bilinear, PIL), ToTensor and Normalize.""" | |
| image = image.convert("RGB").resize((size, size), Image.Resampling.BILINEAR) | |
| return ((np.asarray(image, dtype=np.float32) / 255 - MEAN) / STD).transpose(2, 0, 1) | |
| class GridPredictor: | |
| def __init__(self, model, threads=None): | |
| if threads is not None and threads < 1: | |
| raise ValueError("CPU threads must be positive") | |
| options = ort.SessionOptions() | |
| if threads: | |
| options.intra_op_num_threads = threads | |
| self.session = ort.InferenceSession(str(model), options, providers=["CPUExecutionProvider"]) | |
| self.info = json.loads(self.session.get_modelmeta().custom_metadata_map["grid_vision"]) | |
| def inputs(self, source): | |
| """Model input for a challenge image, or a dataset item folder holding image.jpg.""" | |
| source, size, tiles = Path(source), self.info["size"], self.info["tiles"] | |
| if source.is_dir(): | |
| found = next((source / name for name in IMAGE_NAMES if (source / name).is_file()), None) | |
| if found is None: | |
| raise ValueError(f"No image in {source} (expected one of {IMAGE_NAMES})") | |
| source = found | |
| with Image.open(source) as opened: | |
| image = opened.convert("RGB") | |
| if tiles == 9: | |
| # Same rounding as training's grid_boxes. | |
| w, h = image.size | |
| xs, ys = [round(w * i / 3) for i in range(4)], [round(h * i / 3) for i in range(4)] | |
| return np.stack( | |
| [ | |
| preprocess(image.crop((xs[c], ys[r], xs[c + 1], ys[r + 1])), size) | |
| for r in range(3) | |
| for c in range(3) | |
| ] | |
| ) | |
| return preprocess(image, size)[None] | |
| def probabilities(self, inputs): | |
| """Per-class probabilities, shaped (classes, cells).""" | |
| output = self.session.run(None, {self.session.get_inputs()[0].name: inputs})[0] | |
| return output.T if self.info["tiles"] == 9 else output[0] | |
| def predict(self, source, target): | |
| name = target_name(target) | |
| if name not in self.info["classes"]: | |
| raise ValueError(f"Unknown target {name!r}; supported: {self.info['classes']}") | |
| probabilities = self.probabilities(self.inputs(source))[self.info["classes"].index(name)] | |
| cutoff = self.info["thresholds"].get(name, self.info["threshold"]) | |
| return { | |
| "target": name, | |
| "threshold": cutoff, | |
| "selected_cells": [int(i) for i in np.flatnonzero(probabilities >= cutoff)], | |
| "probabilities": probabilities.tolist(), | |
| } | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter | |
| ) | |
| parser.add_argument("--model", required=True) | |
| parser.add_argument("--image", required=True, help="Challenge image, or a dataset item folder") | |
| parser.add_argument("--target", required=True) | |
| parser.add_argument("--threads", type=int, help="CPU threads (default: onnxruntime's choice)") | |
| args = parser.parse_args() | |
| print( | |
| json.dumps( | |
| GridPredictor(args.model, args.threads).predict(args.image, args.target), indent=2 | |
| ) | |
| ) | |
| if __name__ == "__main__": | |
| main() | |