#!/usr/bin/env python3 """Oracle onnxruntime pour la parité PP-OCRv6 tiny (burn vs ORT). Deux modes par réseau : * « exact » : les tenseurs d'entrée pré-traités par burn_ppocr (fichiers .f32 little-endian + formes dans le manifeste) sont donnés à ORT tels quels → ne compare que les réseaux ; * « own » : ce script refait le pré-traitement de PaddleOCR lui-même (PIL BILINEAR, BGR, mean/std, crops à partir des boîtes JSON de burn_ppocr) → compare réseaux + pré-traitement. Usage : ppocr_ref.py --image hello.png --det det_pads.onnx --rec rec_pads.onnx \ --work DIR # DIR contient boxes.json (+ det_input.f32, rec_input.f32, manifest.json) Écrit dans DIR : det_out_exact.f32, det_out_own.f32, rec_out_exact.f32, rec_out_own.f32 et ref.json (formes). """ import argparse import json import math import os import numpy as np import onnxruntime as ort from PIL import Image MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32) STD = np.array([0.229, 0.224, 0.225], dtype=np.float32) def det_resize_dims(w, h, limit, max_side): ratio = limit / min(w, h) if min(w, h) < limit else 1.0 if max(w, h) * ratio > max_side: ratio = max_side / max(w, h) rw, rh = int(w * ratio), int(h * ratio) rw = max(int(round(rw / 32) * 32), 32) rh = max(int(round(rh / 32) * 32), 32) return rw, rh def det_own_input(img, limit, max_side): rw, rh = det_resize_dims(img.width, img.height, limit, max_side) resized = np.asarray(img.resize((rw, rh), Image.BILINEAR), dtype=np.float32) # HWC RGB bgr = resized[:, :, ::-1] / 255.0 norm = (bgr - MEAN) / STD return norm.transpose(2, 0, 1)[None].astype(np.float32) def crop_rotate(arr, x0, y0, x1, y1): c = arr[y0:y1, x0:x1] h, w = c.shape[:2] if w > 0 and h / w >= 1.5: c = np.rot90(c) return c def rec_own_input(img, boxes, rec_h, img_w): arr = np.asarray(img) crops = [crop_rotate(arr, *b) for b in boxes] out = np.zeros((len(crops), 3, rec_h, img_w), dtype=np.float32) for i, c in enumerate(crops): h, w = c.shape[:2] if h == 0 or w == 0: continue rw = min(max(int(math.ceil(rec_h * w / h)), 1), img_w) r = np.asarray(Image.fromarray(c).resize((rw, rec_h), Image.BILINEAR), dtype=np.float32) bgr = r[:, :, ::-1] / 255.0 norm = (bgr - 0.5) / 0.5 out[i, :, :, :rw] = norm.transpose(2, 0, 1) return out def read_f32(path, shape): return np.fromfile(path, dtype=" 0: xr = read_f32(os.path.join(work, "rec_input.f32"), shape) yr = rec.run(None, {rin: xr})[0] yr.astype("