The white flashing was the top fade: the live raisers were not repainting it

Oliver: "what is this white flashing while applause in the upper right corner of
the crowd". With the photographers switched off entirely it was still there, so
it was never them — it was mine, from this morning. The top fade is baked into
the cached stand, and drawRaisers was painting a spectator's box straight over
it with only the dim applied. Every time that spectator stood up his box lost
the fade and lit up; every time he sat down it came back. Measured on the canvas:
a 146-luminance jump, twice a second, in exactly the two places raisers sit near
the top of the picture.

Both stand treatments now come from one function each and are applied in both
places. The gradient is built in user space, so filling a raiser's sub-rect with
it picks up the right alpha for free. Probed again after the fix: zero bright
pops during applause and during the wave, against the four hot spots before.

While chasing it, two real detector faults turned up and are fixed too: a blob
may not be a pale block (a re-rolled cream shirt is "new material" by the
stand-turned-person test but nothing rises), and it may not cover something
already bright (a genuine arm drawn over a white shirt deletes a white block,
which flashes just as hard). 94 raisers survive both rules.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-21 14:55:13 +02:00
1 parent 93c4a21be5
commit ca3e72d0a9
8 files changed
+81 -47

No files matched your search

+20
View File
@@ -76,6 +76,19 @@ HUD = [(6, 6, 156, 62), # scoreboard + the GAME/SETS panel under it
(170, 6, 264, 30)] # the BLOOD panel, clear of the quit chip
MIN_AREA, MAX_AREA = 150, 3000 # an arm blob: one pair of raised arms, or one arm
# ...AND IT HAS TO BE ARMS GOING UP OVER STAND. Oliver: "what is this white flashing while applause
# in the upper right corner of the crowd" — and with the photographers switched off entirely it was
# still there, so it was never them. Two different blobs were doing it, and neither is a raise:
# PALE SWAPS — the roll repainted somebody's cream shirt, and `stand()` (which only asks whether a
# pixel matches its row's modal colour) called the old one stand. Nothing rises; a white block
# just changes pattern at 3.5 Hz.
# BRIGHT COVER-UPS — a genuine arm, but drawn over something ALREADY BRIGHT (a white shirt in the
# row behind, lum 239). Raising him deletes a white block and sitting him down brings it back,
# which flashes exactly as hard as adding one would.
# So a blob must be warm-ish, must not be a pale block, and must ADD light to something dark.
PALE_MAX = 0.35 # of the blob may be bright-and-colourless (a cream shirt)
COVER_MAX = 150 # ...and what it covers in the seated frame must be darker than this
LIFT_MIN = 12 # ...by at least this much: arms over wall, never over a white shirt
ARM_H, ARM_W = (10, 70), (8, 90) # ...and its shape, in px of the 1408x768 sheet
BAND = 8 # rows the background colour is sampled over
PAD = 3 # px of margin around a raiser's box
@@ -127,6 +140,13 @@ def raisers(A, B):
# sheet; arms that rise out of empty stand belong to nobody and read as floating hands.
if bgA[sl[0].stop:min(A.shape[0], sl[0].stop + 6), sl[1]].mean() > 0.55:
continue
# ...AND IT HAS TO BE A RAISE (see PALE_MAX / COVER_MAX / LIFT_MIN above).
m = lab[sl] == i + 1
px, was = B[sl][m].astype(int), A[sl][m].astype(int)
if ((abs(px[:, 0] - px[:, 2]) < 26) & (px[:, 0] > 140)).mean() > PALE_MAX:
continue
if was.mean() > COVER_MAX or px.mean() - was.mean() < LIFT_MIN:
continue
out.append([sl[0].start, sl[1].start, sl[0].stop, sl[1].stop, i + 1])
return out, lab
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB