The applause moves down out from under the scoreboard

Oliver: "in the upper parts of the crowd there seems to be a lot more action
going on, but I can barely see it because the hud is covering it." Measured, 31
of 134 raisers were being drawn under the board or the blood panel — a quarter
of every cheer spent where nobody can see it.

The cause is structural: a raise is only detectable where there is empty stand
above somebody's head, and the sheet only offers that above the top row of each
seating block. One of those rows is at the very top of the picture, which is
where the scoreboard lives.

So both ends are fixed. The two arms-up rolls now ask for the standers to be in
the lower two thirds only, and the pass drops any raiser whose box centre falls
under the board or the blood panel. 92 of 101 raisers now sit below the board's
bottom edge, against 103 of 134 before — and because "how many join in" is a
fraction of the table, pruning the invisible ones makes every cheer denser where
it counts. Measured churn during a won game: 2-5.5% of the mid and lower stand
changing every 90 ms, against 0.1-1% under the HUD.

The re-roll also came back with 41 spectators owning both raised poses, up from
28, so more of them clap rather than just going up and down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-21 14:40:22 +02:00
1 parent b34a9159a7
commit 93c4a21be5
11 files changed
+148 -138

No files matched your search

+27 -1
View File
@@ -62,6 +62,19 @@ GRADE_REF = '76ea1d0'
# borrows the hard-court sheet and does its own dimming in `COURTS.dim`, so it is fixed there.
COURTS = [('x_crowd', 0.72), ('x_crowd_c', 1.0), ('x_crowd_h', 1.0)]
# WHAT THE HUD EATS. A raiser drawn under the scoreboard is a draw call nobody sees, and worse: the
# "how many join in" fraction spends part of every cheer on them. Oliver: "in the upper parts of the
# crowd there seems to be a lot more action going on, but I can barely see it because the hud is
# covering it." Measured on the sheet before this rule, 31 of 134 raisers sat behind the board or the
# blood panel. They are dropped here, which also makes the visible applause denser for free.
# In LOGICAL px of the PORTRAIT layout, which is the primary target: the board sits at (6,6) 150x42
# with its game/sets panel under it, the blood panel is up in the right corner, and the stand band is
# about 195 px tall (render.js: standsBottom - AD_H). Landscape has a shorter band, so the same
# fractions cover more of the sheet there — this rule is conservative, never over-eager.
HUD_W, HUD_BAND = 270, 195
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
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
@@ -138,6 +151,17 @@ def merge(boxes):
return boxes
def visible(boxes, h, w):
"""Drop the raisers the HUD sits on top of — see HUD above."""
out = []
for y0, x0, y1, x1, m in boxes:
cx, cy = (x0 + x1) / 2 / w * HUD_W, (y0 + y1) / 2 / h * HUD_BAND
if any(a <= cx <= c and b <= cy <= d for a, b, c, d in HUD):
continue
out.append([y0, x0, y1, x1, m])
return out
def grade(src, ref):
"""Per-channel histogram match: the roll's colours redistributed onto a court's own look.
Returns a function, so the pair can be graded with ONE transform."""
@@ -199,7 +223,9 @@ def main(review):
print(f' pose {bit + 1}: {len(arms)} arm blobs, {moved:.1f}% of the sheet '
f'(the roll itself drifted {drift:.1f}%)')
boxes = merge(boxes)
rows = write_table(boxes, h, w, len(frames))
seen = visible(boxes, h, w)
print(f' {len(boxes) - len(seen)} of {len(boxes)} raisers dropped: the HUD covers them')
rows = write_table(seen, h, w, len(frames))
both = sum(1 for r in rows if r[4] == 3)
print(f'{len(rows)} spectators can move, {both} of them with both poses (a real clap)')