Measure the faces already found rather than finding them again
Benchmarks / CPU and I/O (per commit) (push) Successful in 3m13s
Benchmarks / Frame budget (on demand) (push) Skipped
Build and test / Desktop (Linux) (push) Failing after 54s
Build and test / Layer separation (push) Failing after 1s
🐳 Android image / Build and push (push) Successful in 1s
Build and test / android-image (push) Successful in 2s
Traceability / Requirement traces (push) Successful in 52s
Build and test / Android (aarch64) (push) Successful in 30m6s

Every face stored before its quality was kept holds a unit vector, and
V14 forgot the run marker of each image holding one so that the next
sweep would look again. Looking again meant detecting again: a whole
re-detection per image, with every suggestion on it thrown away and the
confirmations carried across by box overlap, to recover one number.

The sweep now has a measuring pass between the proxy repair and the
un-indexed images. It lists every image holding an unmeasured face,
fetches the original once, warps each stored face from the landmarks it
already has, embeds it, and writes the raw vector and its length over
the old row. Ids, boxes and identities are untouched; the marker is
re-written fresh so the sync exports the measured vectors. A face whose
landmarks no longer make a warp is dropped, as detection would have
refused to store it. `faces_unindexed` leaves those images to the
measuring pass, so the V14 deletion no longer costs a second detection.
This commit is contained in:
2026-09-11 21:50:12 +02:00
parent 8b3abdb787
commit 16f3fb41a3
7 changed files with 578 additions and 48 deletions
+5 -2
View File
@@ -816,8 +816,11 @@ here, and it is the phone and tablet story that should decide whether it gets bu
anything downstream sees them. A probe's confidence (§9.1) is computed from the references it
matched; a reference's confidence hears nothing from a probe. A face whose quality was never
recorded is admitted to the gallery — a rule that cannot be checked admits rather than excludes —
and schema V14 forgets the run marker of every image holding one, so the next indexing pass
measures it.
and the next indexing pass **measures** it: `faces_unmeasured` lists every image holding one, and
each such face is embedded again from the native render with the landmarks it already has, the raw
vector written over the old one and its id, box and identity untouched
(`faces::record_measurements`). No detector runs and no suggestion is lost — the cost is the
original fetched once more, since the length exists only at the moment of embedding.
**The algorithm.** Constrained average-link agglomeration over the probability graph, merging while
the average pairwise probability exceeds **0.9** and no cannot-link is violated. Average-link rather