What it does

Capture Coach evaluates photographs of scrap electronic equipment. For each photo it says whether it is usable, needs a retake, or needs review, names what is wrong, and gives an instruction that carries a measured fact about that specific photograph.

How it works

Five detectors, each an ordinary physical measurement over the region the view is actually judged on, not the whole frame:

| Rule | What it measures | Threshold | Margin on the practice set |

| underexposed | share of the subject with no recoverable detail | ≥ 0.65 | 0.450 | | glare_or_overexposed | the subject's brightness floor — a high floor means no shadow detail anywhere | ≥ 125 | 32 | | blur | variance of a 4-neighbour Laplacian | < 32 | 12.9 | | framing | the label's margin to the nearest border, or the device's contact along a side edge | < 0.02 / ≥ 0.40 | 0.057 / 0.131 | | label_obstructed | the orange label's outline solidity | < 0.93 | 0.042 |

Privacy masks are detected first and excluded from every measurement — a black box drawn over a serial number would otherwise manufacture both a blur finding and an underexposure finding. The app draws them hatched and labelled "excluded from every measurement, not counted as a defect".

Between each hard threshold and the next there is an abstain band. A photograph that lands in one is reported as needs_review with the band, the measured value and the pass mark, rather than being guessed at.

It all runs in the browser. OpenCV compiled to WebAssembly, bundled with the app — never a CDN. No backend, no account, no API key, and no photograph leaves the machine. Load it once and it works with the network switched off.

Results

Measured by npm run eval, offline, over the 34 supplied practice images, and visible in-app under Scorecard:

  • 34/34 status agreement
  • 0 false alarms on the 11 clean photographs
  • precision and recall 1.00 on all five issue codes
  • 9/9 on set-level missing views
  • abstained on 2/34 = 5.9%, the same rate as the supplied answers
  • 652 ms median per photo; 37.8 s for all 34, decode included

100% on 34 images is a fitted result, not a generalisation claim. The thresholds were chosen by inspecting the margins on that same set. What defends them on photographs nobody on this team has seen is not the score: it is that every rule is a physical measurement with a stated margin and a stated failure direction, and that the honest list of what is untested is in the repository and is not short.

Where AI contributes

Nowhere, in this release, and the app says so on every card. The five detectors need no model, no key and no network.

The architecture confines a model to five questions the rules genuinely cannot answer — whether the device is fully in frame where its shadow blurs the boundary, whether the port area is actually visible, whether the content matches the selected view, confirmation of the 0.042-margin obstruction rule, and which of several simultaneous defects to lead with. The precedence rule is rules own physics, the model owns meaning, physics wins, and a model reporting a defect with no rule support produces needs_review, never a retake. docs/AI_AND_RULES.md has the full table.

We did not ship recorded model responses, so we do not claim a model contribution we cannot show.

Known limitations

The full list is docs/LIMITATIONS.md. The three that matter most:

  1. Obstruction has a 0.042 margin on five positive examples — the rule most likely to break on unseen photographs.
  2. Port visibility is switched off. With no AI configured, a rear/ports photograph that is sharp, well lit and well framed but shows no connectors may be reported as usable.
  3. Three code paths have never run on real data — the whole-frame fallback, the too-small-to-measure path, and the view/content mismatch rule. Each is built to abstain rather than accuse, because a wrong abstain costs less than a wrong retake.

Built with

TypeScript · Vite · Tailwind · OpenCV (WebAssembly, bundled) · Python + OpenCV + NumPy

Try it

Open the URL, click Load practice set, and select everything in your copy of STUDENT_REVIEW/images/ together with photo_sets.csv and manifest.csv. The supplied photographs are not redistributed in the repository or the deployed bundle, so the app asks you to point at the copy you already have.

Built With

Share this project:

Updates

Submission history