Port step 4: measure the anchor and the mouth, condition on its own
`stabilize` is three things wearing one name, and it is now three functions in two stages: `flow/measure/anchor` fits the rigid transform, `flow/condition` smooths its parameters, `flow/measure/mouth` measures the lip rings through the result. Parity is on the COMPOSITION and not on the pieces -- a split that agreed function by function and not end to end would be a split rather than a port. The oracle now drives `stabilize` at three configurations and the port agrees to 1e-9 on ref, rigid, transforms, outer, inner and aperture, plus `smoothContours` at three radii. Two of the three configurations are at aspect 0.5625, a 1080x1920 phone clip, because at aspect 1 `pick` is the identity: a port that dropped the anisotropy correction outright would pass every other assertion in the suite. 148 tests, up from 134. Three decisions worth the reading time. `makeXform` is not ported, and its absence takes the face oval with it. It centres on the oval's bounding box and zooms until the face is 80% of the raster height, so every vertex it touched carried a cropping decision made once, at analysis time, from one frame's landmarks. Geometry belongs in the node's own local space with the framing as a transform on a node, so this is a deletion. The oval's only other consumer was the placeholder plate outline, which is painting. The residual is taken against the RAW fit, and the prototype took it against the smoothed one. That is the only deliberate numeric divergence here, and parity is kept by asserting `anchor/residuals` on exactly what the prototype handed it. The number's job is to say whether a section is stabilisable at all; folding the smoothing error into it makes a slider look like a property of the footage, and docs/architecture.md lists the residual under stage 3, which requires it to be knob-free. `condition/anchor` therefore replaces `:transforms` and leaves `:residual` alone. The stage order is not the strict chain the table in docs/architecture.md looks like, and that document now says so. The fit is knob-free, conditioning smooths it, and the rings are measured *through* the conditioned transform -- so `anchor avg` does re-run the ring mapping, which is a few hundred frames of twenty points. The guarantee was only ever about the part that reads a source pixel, and that part never sees a transform. Two things fall out and are asserted rather than assumed. Smoothing and subsampling commute, because both are per-slot, which is what lets `vertices` stay a stage-5 knob downstream of a stage-4 one -- and it is also why the port can smooth the full twenty slots where the prototype smooths eight and still match. And `condition/contours` is `geom/moving-average` per vertex per axis rather than its own clamped window, so "radius 2" cannot come to mean two different things at the two knobs. One dead end recorded so nobody walks it twice: the synth's head is perfectly rigid -- its jitter is a whole-head translation, which a similarity absorbs exactly -- so every frame's rigid configuration is congruent with frame zero's and the Procrustes mean IS frame zero to 1e-15, jitter or none. "The reference is the mean and not frame zero" cannot be asserted on this track and is asserted in geom-test, where the two can differ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
11192d61c6
commit
942e2f38ab
10 changed files with 494 additions and 1 deletions
|
|
@ -151,6 +151,16 @@ source pixel.** Stage 4 is separated from 3 only because `contour avg` and
|
|||
`anchor avg` are knobs and the rest of stage 3 is not; splitting them means
|
||||
dragging that slider does not re-run the interior extraction.
|
||||
|
||||
That last clause is the guarantee, and it is narrower than the table's ordering
|
||||
looks. Stage 3 is not one pass that finishes before stage 4 begins. The anchor fit
|
||||
is knob-free; conditioning smooths its four parameters; the head-local rings are
|
||||
then measured *through* the conditioned transform — so `anchor avg` does re-run
|
||||
the ring mapping, which is a few hundred frames of twenty points and free. What it
|
||||
must not re-run is the part that reads a source pixel, and that part takes the
|
||||
landmarks and the frames and never the transform, so it does not. Built as
|
||||
`measure/anchor` → `condition/anchor` → `measure/mouth` → `condition/contours`,
|
||||
and stage 7's eyes, brows and interior follow the same shape.
|
||||
|
||||
### Where the current code lands
|
||||
|
||||
| Now | Stage |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue