--- license: apache-2.0 pipeline_tag: image-classification library_name: onnxruntime language: [en] tags: - image-classification - document-ai - form-field-detection - onnx - open-weights metrics: - accuracy --- # form-field-v1-state — open-weight **A 96k-parameter filled/empty classifier for detected form fields.** Given a cropped field, it reads whether the field is **filled** (filled / checked / signed) or **empty** (empty / unchecked / blank) — a single shared, detector-agnostic model that supplies state for any of the `form-field-v1` detectors. ~0.4 MB, CPU-fast, Apache-2.0, runs via ONNX Runtime with no custom code. Part of the `form-field-v1` family — pair it with [`-nano`](https://huggingface.co/nutrientdocs/form-field-v1-nano) (open) or [`-small`](https://huggingface.co/nutrientdocs/form-field-v1-small) / [`-medium`](https://huggingface.co/nutrientdocs/form-field-v1-medium) (commercial). - 🎯 **Try it:** [form-field-v1-demo](https://huggingface.co/spaces/nutrientdocs/form-field-v1-demo) - 🏆 **Leaderboard:** [form-field-v1-leaderboard](https://huggingface.co/spaces/nutrientdocs/form-field-v1-leaderboard) - 📊 **Benchmark:** [form-field-v1-benchmark](https://huggingface.co/datasets/nutrientdocs/form-field-v1-benchmark) ## What it does Field detectors locate `Text`, `Choice`, and `Signature` widgets; this model answers the follow-up question **"is that field filled?"** on the detected crop. It takes a grayscale field crop, letterboxes it to **40×160** (aspect-preserving — form fields are wide, median aspect ~3.3, so a square resize destroys thin printed text), and outputs a binary **empty (0) / filled (1)** label. State is mapped per type: Text → filled/empty, Choice → checked/unchecked, Signature → signed/blank. ## Results Binary field-state accuracy, one shared evaluation. | | Accuracy | |---|---| | **form-field-v1-state** (this model) | **0.981** | | Training-free ink heuristic | 0.915 | On a held-out synthetic split it reaches **0.981** vs a training-free ink-presence heuristic's **0.915**. On a real filled form (the ACME credit-card application, 25 fields) it matches the heuristic at **23/25**. ## What's in this repo | File | | |---|---| | `model.onnx` | ONNX graph, input `1×1×40×160` grayscale, output `logits [n,2]` | | `state_cnn.pt` | PyTorch state dict (depthwise-separable CNN, 96k params) | Classes: `0 = empty`, `1 = filled`. ## Usage (ONNX Runtime) ```python import numpy as np, onnxruntime as ort from PIL import Image sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"]) def letterbox(crop, th=40, tw=160): # aspect-preserving, pad 255 (paper) g = crop.convert("L"); w, h = g.size s = min(tw / w, th / h); nw, nh = max(1, round(w * s)), max(1, round(h * s)) out = Image.new("L", (tw, th), 255); out.paste(g.resize((nw, nh), Image.BILINEAR), ((tw - nw) // 2, (th - nh) // 2)) return np.asarray(out, np.uint8) crop = Image.open("field_crop.png") # a detected field, cropped from the page x = (((letterbox(crop).astype(np.float32) / 255) - 0.5) / 0.5)[None, None] # normalize, shape [1,1,40,160] filled = int(sess.run(None, {sess.get_inputs()[0].name: x})[0].argmax(1)[0]) == 1 ``` ## License & data Apache-2.0. Trained on synthetic form renders (empty + filled + handwritten field crops, with on-the-fly augmentation for scan robustness); no PII. ## About the author This project is maintained and funded by [Nutrient](https://nutrient.io/) - The deterministic document infrastructure enterprises run their highest-stakes workflows on: replayable output, clear exceptions, and full audit trails on the messy, regulated documents where AI alone breaks.