The optimizer path is trying to do one slippery thing:
Lay a sheet of graph paper over the source image, imagine what each output cell ought to feel like, then force every final cell to choose a real source pixel nearby without letting the whole image turn into soup.
When it works, the result feels like the image finally committed to one lattice.
When it fails, this map is here to answer:
Where did the machine start negotiating with itself too much?
The first structural cut now gathers that cargo into `_OptimizerPrep` before snap and refine begin. That does not make the algorithm better by itself, but it makes the machine easier to see: preparation builds the map, snap and refine walk it.
The old k-means paint-by-number scout has been cut. It was letting coarse color partitions masquerade as geometry, and that did not fit the optimizer's core story.
## Stage 2: The optimizer lays down a regular UV grid
Functions:
-`_make_regular_uv(...)`
-`_make_patch_offsets(...)`
Key outputs:
-`uv0`
-`uv0_t`
-`offsets_t`
Meaning:
This stage drops the graph paper onto the mural.
`uv0` is not an optimized warp. It is a perfectly regular lattice built directly from:
- source width and height
- inferred output width and height
- inferred phase
Each output cell gets one normalized coordinate pair saying, "my center currently lands here."
Then `_make_patch_offsets(...)` builds a little stencil of nearby offsets around each center. Those offsets are used to ask, "what does the neighborhood around this cell center look like?"
## Stage 5: Snap every output cell to one real nearby source pixel
Function:
-`_snap_output_to_source_pixels(...)`
Key inputs:
-`uv_t`
-`representative_t`
-`source_reference_t`
-`source_reliability_t`
Key working variables:
-`candidate_x`, `candidate_y`
-`candidate_colors`
-`representative_match`
-`source_match`
-`base_energy`
-`desired_delta_x`
-`desired_delta_y`
-`desired_delta_diag`
-`desired_delta_anti`
-`selected`
Meaning:
This is the first moment the optimizer has to stop talking and actually place stones in the wall.
For each output cell:
1. it looks at a fixed `5x5` neighborhood of nearby source pixels around the UV center
2. it scores those real pixels against both portraits
3. it blends those portrait scores using `source_reliability_t`
4. it repeatedly asks whether the chosen pixel agrees with the colors its neighbors are choosing
5. it picks one real source pixel
The delta maps matter here.
They encode the desired color jump from one cell to the next:
- left to right
- top to bottom
- main diagonal
- anti-diagonal
Those desired jumps are themselves blended between:
- the soft representative portrait
- the hard source-detail portrait
Natural-language picture:
Snap is a mason walking across the empty wall, picking one real stone for each slot while glancing left, right, up, and diagonally to keep the joints plausible.
Then `_harden_binary_alpha_selection(...)` makes an extra binary decision for uncertain alpha cells:
- if this cell should really be foreground, force the best opaque candidate
- if this cell should really be background, force the best transparent candidate
That stops fuzzy half-alpha picks from surviving into the final raster.
## Stage 6: Expand the search space for refine
Functions:
-`_build_candidate_positions(...)`
-`_reference_match_energy(...)`
-`_blend_reference_delta_map(...)`
Key outputs:
-`candidate_x`, `candidate_y`
-`candidate_colors`
-`base_energy`
-`relax_base_energy`
Meaning:
After snap, the optimizer opens a larger local search window for each cell.
These candidates are not just a fixed square anymore. The builder also adds:
- the strongest edge peak for the cell
- gradient-guided offsets along the local edge direction
So the refine stage can reach sharper alternatives than the original snap neighborhood would have seen.
Each candidate now accumulates several costs:
- anchor match: how far it strays from the snapped output
Now refine lays several nearby stones on the scaffold around each slot so it can ask whether a slightly different local arrangement would make a cleaner wall.
## Stage 7: Relax into a soft field before going fully discrete again
Function:
-`_relax_candidate_selection(...)`
Key variables:
-`probs`
-`context_colors`
-`final_energy`
-`relaxed_context`
-`handoff_energy`
-`mode_selected`
Meaning:
This is the optimizer taking a deep breath before it starts making hard yes/no choices again.
Instead of choosing one candidate per cell immediately, it keeps a soft probability distribution over the candidates.
At each relaxation step:
1. it computes the expected color for each cell from those probabilities
2. it scores every candidate against that soft neighborhood
3. it adds structure terms for adjacency, motif, and line continuation
4. it cools the temperature and sharpens the distribution
There are two families of structure terms here:
- anchor-facing terms: stay consistent with the snapped lattice
- source-facing terms: stay consistent with the hard source portrait
Natural-language picture:
This is wet plaster. Nothing is set yet, but the stones are starting to lean into a coherent arrangement.
At the end of relax, the optimizer keeps two things:
-`selected`: the best discrete choice after the handoff energy
-`mode_selected`: the pure modal choice from the soft distribution
That is the machine hedging its bets before the next stage hardens everything again.
## Stage 8: Greedy discrete refine
Function:
-`_discrete_refine_output(...)`
Key variables:
-`selected`
-`best_selected`
-`best_score`
-`candidate_energy(...)`
-`loss_history`
Meaning:
Now the optimizer goes cell-by-cell again, but with a richer energy than snap had.
It starts from:
- the relaxed handoff selection
- the relaxed mode selection
Then it repeatedly:
1. computes the current selected colors
2. scores every candidate against the current neighborhood
3. takes the per-cell argmin
4. measures the full structure score of the resulting lattice
5. remembers the best discrete state it has seen
The structure score in `_structure_score(...)` mixes:
- source-boundary agreement from direct source sampling
- adjacency agreement with the snapped anchor
- motif agreement with the snapped anchor
- line agreement with the snapped anchor
- adjacency agreement with the hard source portrait
- motif agreement with the hard source portrait
- line agreement with the hard source portrait
Natural-language picture:
This is the foreman walking the wall in passes, replacing one stone at a time wherever a better local fit appears, but still judging the whole wall by whether the mortar lines and repeated motifs feel right.
When refine finishes, it compares:
- the best greedy-refined state
- the relaxed mode state
and keeps whichever one has the better full structure score.
Then it hardens alpha again before producing the final `target_rgba`.
- the machine still maintains two overlapping portraits of the same lattice, even though refine is now source-first and only snap still arbitrates between them
- snap, relax, and refine all carry slightly different versions of adjacency, motif, line, and delta agreement; the same idea is being said three times with different accents
- the candidate generator is local and the solver is discrete, but the vocabulary around it still sounds like a continuous deformation engine
- the main entry point is now honestly named `optimize_lattice_pixels(...)`, the k-means boundary scout is gone, prep is split from decision-making, and refine no longer consults the representative portrait; those cuts removed four contradictions from the previous map
3. Decide whether snap still needs both portraits everywhere.
Refine is already source-first now, so the next big question is whether snap still needs all of its portrait arbitration machinery or only the parts that genuinely stabilize hard cases.