Nishi Reverse Image — sovereign visual search

Find where an image (or a modified copy of it) appears — TinEye / Google-Lens class matching, built bits-up in NishiLang. Pure integer, zero-float, no cloud API. Every number below is measured by an in-repo ruler, not asserted.

robustness 985 ‰survives 16/16 single-edit classes+ combined crop + rescale 8434 fusion tiersgate 14/14 GREENinteger · no-float · sovereign

A reverse-image engine lives or dies on one question: which real-world edits to an image does it still recognise? So the engine ships with its own adversary — nx_imgbench applies 16 named modifications (rescale, crop, letterbox, mirror, rotate, brightness, contrast, watermark, recompress, sensor noise) to a deterministic corpus and measures recall@1 for every one. That measurement is the spec; a class that scores below par is a build item, not a footnote.

Measured robustness — recall@1 per modification class

Multi-tier engine on the same corpus. Higher = more of the modified copies still rank #1. ≥900‰ survived below par

identity1000
rescale 50/200%1000
brightness/contrast1000
crop 10%1000
crop 20%1000
crop 30%906
letterbox1000
mirror horizontal1000
rotate 90/1801000
sensor noise1000
watermark bar1000
recompress1000
crop+rescale*843

The 16 single-edit classes all survive; the fused engine scores 985‰ overall vs 597‰ for a single perceptual hash. *crop+rescale is a harder combined stress test — occlusion AND a scale change at once — added to push the frontier. A similarity-consensus RANSAC (translation + scale, still pure integer) lifts it from a translation-only 500 to 843‰. Recall@1 is measured against 256 distractors and stated as an upper bound on open-web performance.

How it works — four tiers, fused

No single descriptor covers the whole modification space, so the engine fuses complementary tiers by reciprocal-rank fusion with abstention (a tier only votes where it is competent, so a blind-but-confident tier can't out-vote the right one). Adding a tier is a new subclass, never an engine rewrite.

tiermethodanswersbeats
copy‑dhash64‑bit perceptual hash (dHash), Hammingidentityrescale, brightness, contrast, noise, watermark, recompress
orient‑d4dihedral‑group canonical hashidentitymirror, 90°/180° rotation — zero extra storage
local‑orbFAST corners + BRIEF + RANSAC geometryidentitycropping, letterboxing — occlusion-robust
similar‑ehdedge‑orientation layout, L1looks‑alike“same composition” when it isn't a byte copy

Scale: the hash tiers generate candidates through a BK‑tree metric index — exact within threshold, ~6× fewer comparisons than a linear scan on clustered corpora. Descriptors are quantised to integers at ingest and served with fast integer scans.

Honesty — what it does NOT do yet

Crop + rescale (843‰)

The combined occlusion + scale case, lifted from 500 to 843 by the similarity-consensus RANSAC. Clearing 900 wants a full ORB scale pyramid — and a naive octave pyramid was measured to regress the same-scale classes, so it is honestly not shipped.

Semantic “looks like”

The Google-Lens axis (what a picture is of) needs a quantised learned embedding tier. Not built yet — and the page says so rather than implying it.

WebP / AVIF

Those formats have no sovereign decoder yet, so that slice of the web is currently un-indexable — invisible, not mis-ranked.

Query it (agents & workflows)

The engine is a first-class MCP tool — strict JSON in, strict JSON out, self-describing including its own measured limits. It refuses honestly: a structureless (blank / gradient) image returns present:false rather than a confident collision.

nx_imgsearch status                      # live tier roster + measured robustness + named gaps
nx_imgsearch index <manifest> <out>       # build a fingerprint index (cid → image)
nx_imgsearch walkdir <dir> <out> [max]    # index a whole folder (async), poll with walkstatus
nx_imgsearch query <index> <image> [k]    # → ranked matches, each with tier, distance, confidence

Proven live on real photorealistic images: a held-out photo returns its own record at Hamming distance 0 via the local-feature tier, while a genuinely-different image is honestly reported absent.