ONE palette gate replaces four feature-picked ones
Oliver, on the brute's fall frames: "now the fall zombie has a different skin tone.. man this is all so tiresome." Both halves were right. The skin IS twenty points lighter across that sheet, and the tiresome part is mine: I had been adding one hand-picked gate per drift I discovered — redness, then hue, then `changed`, then no-grids — which is a loop with no end, because naming features is not the same as comparing pictures. `kit` names four: shirt redness, shorts brightness, shorts hue, near-white fraction. Every character breaks a different one. The brute's shirt has no red in it at all, so its reference redness was 0 and blood scored 70-100 against a tolerance meant for a garment. A body face down shows a fraction of the shirt it shows standing, so two of the four move with POSE. And nothing in that list ever measured SKIN, which is exactly how a brute's flesh drifted across a whole sheet with six gates green. The palette gate asks the only question that generalises: are the big colour areas of this frame the same colours as the anchor's? Top SIX by area — the garments and the skin. Proportions ignored, so a pose change is invisible; blood is never in the top six, so a fresh wound cannot look like drift. CALIBRATED BEFORE IT WAS WIRED IN, which is the discipline I skipped all day. Frames known to be right score 0.0-8.5; the drifts we could actually see score 12.0-15.9. The threshold is 10, in the gap. Three formulations were measured and the two that overlapped were thrown away. And every sheet of a variant is now anchored to that variant's FIRST sheet, not to the stage above it. Chaining let a legal hop compound into a drift nobody authorised — the shorts walking -9 to -19 down the wound ladder was that, and so was this. Its first verdict on the existing brute: br_play is the character, and every other sheet sits 15 to 48 away from it. It would have caught all of this on the first roll. Also in: the GRID guard from the same session — the valley-cut rescue would slice a 2x2 sheet into four frames of a torso above someone else's boots, turning a loud failure into a silent one. Asked per cut PIECE, because a body is vertically continuous and a piece with a gap in it caught two of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
df454c5d92
commit
0e92c72457
33 files changed
+312
-19
No files matched your search
+34
-1
@@ -92,6 +92,34 @@ def valley_cuts(ink_cols, x0, x1, n):
|
||||
out.append(lo + int(np.argmin(ink_cols[lo:hi])))
|
||||
return out
|
||||
|
||||
# DO THE FIGURES SHARE A GROUND LINE? That is the invariant every prompt in this project asks for,
|
||||
# and it is the one that tells a ROW from a GRID. An empty-band test does not: in the sheet that
|
||||
# caught this, a 2x2 of a brute falling, the bottom-right figure was tall enough to overlap the top
|
||||
# row and there was no clean horizontal gap anywhere.
|
||||
#
|
||||
# It matters because the valley rescue below will cut ANY sheet into the number of columns it was
|
||||
# asked for — and on a grid each column is a torso above someone else's boots. Four such frames
|
||||
# installed silently and looked, in the log, exactly like a success. The rescue turned a loud failure
|
||||
# into a quiet one, which is the worst trade available in this file; this is the check that stops it.
|
||||
# IS THIS ONE FIGURE, OR TWO STACKED? Asked of each CUT PIECE, not of the sheet. A body is
|
||||
# vertically continuous — head to feet there is no height at which the piece is empty — so a
|
||||
# full-width empty band inside a piece's own extent means the cut caught someone's torso above
|
||||
# someone else's boots.
|
||||
#
|
||||
# Asking it of the whole sheet does not work, and both weaker versions were tried: an empty-band test
|
||||
# on the sheet fails when a grid's bottom-right figure is tall enough to overlap the top row, and a
|
||||
# shared-ground-line test fails because after a bad cut EVERY column reaches the bottom row's feet.
|
||||
# The piece is the only place the question has a clean answer.
|
||||
def split_piece(crop):
|
||||
rows = (crop[..., 3] > 0).any(1)
|
||||
ys = np.where(rows)[0]
|
||||
if not len(ys): return False
|
||||
run = best = 0
|
||||
for y in range(ys.min(), ys.max() + 1):
|
||||
run = 0 if rows[y] else run + 1
|
||||
if run > best: best = run
|
||||
return best >= MIN_GAP * 2
|
||||
|
||||
def frames(a, cuts, want=0):
|
||||
ink = (a[..., 3] > 0)
|
||||
cols = ink.any(0)
|
||||
@@ -122,12 +150,17 @@ def main(sheet, outs, target_h, cuts, anchor, defringe=2):
|
||||
a = key(Image.open(sheet), defringe)
|
||||
b = block_size(a)
|
||||
crops = []
|
||||
for x0, x1 in frames(a, cuts, len(outs)):
|
||||
spans = frames(a, cuts, len(outs))
|
||||
for x0, x1 in spans:
|
||||
sub = a[:, x0:x1]
|
||||
ys = np.where((sub[..., 3] > 0).any(1))[0]; xs = np.where((sub[..., 3] > 0).any(0))[0]
|
||||
crops.append(sub[ys.min():ys.max()+1, xs.min():xs.max()+1])
|
||||
if len(crops) != len(outs):
|
||||
sys.exit(f'ERROR: found {len(crops)} frames, expected {len(outs)} ({sheet})')
|
||||
bad = [i for i, c in enumerate(crops) if split_piece(c)]
|
||||
if bad:
|
||||
sys.exit(f'ERROR: frame(s) {bad} contain two stacked bodies — the sheet is a GRID, not one '
|
||||
f'row ({sheet})')
|
||||
# palette = the colours the generator actually used, on the largest frame
|
||||
big = max(crops, key=lambda c: (c[..., 3] > 0).sum())
|
||||
px = big[big[..., 3] > 200][:, :3]
|
||||
|
||||
Reference in new issue
Block a user