Image 2 Low Poly
One photo in, one editable low-poly mesh per triangle budget out, each scored against the photo through the same locked camera and counted four independent ways. The low-poly geometry itself does the approximation: no texture, billboard, projected photo or uncounted geometry stands in for shape.
Inputs: the reference image (never changed), the subject, the budgets. Worked example: examples/cat/ in the
repository (one orange tabby, budgets 100 / 200 / 500 / 1000).
Before starting
| Situation | Do this |
|---|---|
| One photo, whole subject visible, plain background | the main path |
| A four-legged animal | the shipped proxy template (fit_camera_proxy.py, build_proxy.py) is a quadruped cat; adjust its priors |
| Any other subject | write a proxy template for it first (generalised cylinders per part, catlib/skeleton.py format); the rest of the tools are subject-agnostic |
| Several photos, a video, a scan | out of scope: one view, one camera |
| The user wants colour or texture | flat per-face colours only; say so before starting |
| No Blender | not supported: counting, assembly and every official number need Blender 5.2+ |
Say before starting that everything the photo does not show is inferred, not verified.
Workflow
S below means skills/image-to-lowpoly/scripts. Every script takes --case CASE (or LOWPOLY_CASE). Post
a labelled image at every checkpoint (overlays, clay, wire, eight views): images first, numbers second.
- Case and reference. Make
CASE/reference/reference.png(byte-identical copy of the user's image) and a provenance file with its SHA-256. Never regenerate, resize or edit it. - Fixed targets. Annotate landmarks and image windows by looking at zoomed crops (12 sharp: ear tips,
eyes, nose, four paw contacts, tail base/mid/tip for a cat; adapt the list to the subject), then
python3 $S/preflight_reference.py --case CASE. Look atmask_overlay.pngandlandmarks_overlay.png. The mask excludes the floor shadow and whiskers. - Camera and proxy.
fit_camera_proxy.py --case CASE(CPU, tens of minutes), thenbuild_proxy.py,build_proxy.py --lockandbuild_proxy.py --report. Look at the proxy from all eight views: it is the answer for everything hidden. Then freeze: write the hashes of reference, mask, landmarks, regions, camera, scene, proxy and the evaluation code tocontract/FROZEN.jsonbefore any budget is scored (references/contract.md). - Controls.
make_decimation_baseline.py --case CASE --budget Nfor every budget: Decimate of the proxy to exactly N, and the same after the shared refiner. These are the numbers to beat. - Allocate and build, per budget. Give each budget its own worker and directory
variants/<N>/(references/budget-worker.md). Write the allocation table (region, triangles, rings x sides, reason), build at least two materially different allocations, give each the same short refinement, compare, choose.variants/<N>/build.pywrites acatmesh-1mesh.jsonwith exactly N triangles (assert it), regions, materials and landmark attachments. One closed surface: weld limbs, tail and ears into the body. - Initial checkpoint.
evaluate.py --case CASE --mesh variants/<N>/checkpoints/v0_initial/mesh.json --views. This is the "initial" row. - Refine, measure, look, edit, repeat.
refine_vertices.py(--flips,--freeze-vertsfor faces and any frozen kit),evaluate.py, then look atref_overlay.png,ref_clay.png,ref_wire.pngand the eight views. Make targeted topology edits where the overlay shows the budget misallocated. Keep the best validated checkpoint; the newest need not win. - Blind review.
make_critic_packet.py --case CASE --round Kpacks the photo and neutral-named clay, wire and outline renders. Start a fresh subagent that sees only that folder; turn its findings into budget-neutral geometric edits. Reject any suggestion that is a texture, a card or uncounted geometry. - Finalize and aggregate.
finalize_variant.py --case CASE --budget N --checkpoint TAG --reason "..."copies the checkpoint and re-scores it;aggregate_metrics.pybuilds the cross-budget table and refuses mismatched hashes or counts;make_comparison.pymakes the sheets. - Report and stop. Present the clay/wire sheet with the four counts, the table of initial, final and both controls per budget, the allocation tables, the reviewer's verdicts, and what is wrong. Say where the designed mesh does not beat the control. The user decides what next.
- Timelapse (optional). Record construction stages (
--stages-dirin your build script) and optimiser snapshots (refine_vertices.py --snapshot-dir DIR --snapshot-every K), thentimelapse/timelapse.py --case CASE: the mesh drawn over the photo through the locked camera.
Hard rules
- The count is the evaluated, exported geometry. Four counts (mesh file, evaluated
.blendover every object, re-imported GLB, parsed GLB) must agree and be at most N; aim for exactly N. Never Blender's polygon count (references/counting.md). - Nothing hides triangles or shape. Triangles only, one object, no modifiers, no subdivision, curves, hair, instances, alpha cards, duplicate or degenerate padding, billboards or flat silhouette extrusions.
- The target never moves. Reference, mask, landmarks, windows and camera are made once and hashed. A genuine correction is disclosed and every budget is re-scored.
- No single number decides. IoU, boundary distance, landmarks and leg gaps must not contradict each other, and the clay and eight views must look better. A better score with a worse shape is a regression.
- Weld, do not interpenetrate. Buried triangles are wasted budget and the joins show.
- The optimiser is shared; the allocation is the experiment. Same refiner, same settings available to every budget and to the control.
- Landmarks move with geometry. A landmark is attached to the feature it names; never slide the attachment to improve a number.
- One render at a time. Only
render_variant.pyrenders, and it takes the lock itself. - Materials never count as shape. Flat per-face colours with anatomical meaning; rank geometry on clay and silhouettes only.
- Say what it is not. Inferred hidden side; a ties-the-control result is a tie; heads and thin parts are where these meshes are weakest.
References
| File | Read when |
|---|---|
references/contract.md | setting up a case: layout, units, camera, mesh format, metrics, renders, proxy, landmarks, head kit |
references/budget-worker.md | delegating or doing one budget: procedure, priorities, what to look at |
references/counting.md | the four-way count, hard failures, what is disclosed |
references/lessons.md | what went wrong in the cat run and the rule each failure became |