Show the generator what to copy, not what to replace
The reference sheet is what it imitates, so building that sheet out of the very sprites I was trying to change is why the front-facing player came back front-facing and the side-on runner came back side-on. A batch can now name `ref_only` — the frames it looks at — separately from the frames it replaces: the back view is drawn from the one genuine back-view frame, the charging runner from a front-facing zombie, and each brute wound pair from its own A frame so the injury cannot wander between the two. Also stopped colour-matching a REPOSE. Fitting a differently-posed frame onto the old one's colour statistics is what greyed out the serve shorts; when the pose changes the generator's own palette is the better answer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
01498eddad
commit
67a410e707
4 files changed
+96
-16
No files matched your search
+19
-6
@@ -61,10 +61,18 @@ def density(path):
|
||||
return round(float(((d > 40) & solid[:, :-1]).sum() / max(1, solid.sum())), 3)
|
||||
|
||||
def touches_edge(sheet):
|
||||
"""A CLIPPED figure, not a speck of noise: a run of 8+ ink pixels along a border. The strict
|
||||
version rejected sheets over single stray pixels and cost several regenerations."""
|
||||
a = np.array(Image.open(sheet).convert('RGB')).astype(int)
|
||||
bg = a[0, 0]
|
||||
fg = (((a - bg) ** 2).sum(2) > 3600) & ~(np.minimum(a[..., 0], a[..., 2]) > a[..., 1] + 40)
|
||||
return bool(fg[0].any() or fg[-1].any() or fg[:, 0].any() or fg[:, -1].any())
|
||||
def run(line):
|
||||
n = best = 0
|
||||
for v in line:
|
||||
n = n + 1 if v else 0
|
||||
best = max(best, n)
|
||||
return best
|
||||
return max(run(fg[0]), run(fg[-1]), run(fg[:, 0]), run(fg[:, -1])) >= 8
|
||||
|
||||
def colour_match(src, dst_name):
|
||||
"""Fit the new frame onto the palette statistics of the sprite it replaces, so a redrawn body
|
||||
@@ -83,7 +91,9 @@ def run(name, spec, dry=False):
|
||||
os.makedirs(SCRATCH, exist_ok=True)
|
||||
sprites = spec['sprites']
|
||||
lead = spec.get('ref') # generated for scale, thrown away after
|
||||
ref = ref_sheet(([lead] if lead else []) + sprites, f'{SCRATCH}/{name}_ref.png', spec.get('scale', 2.0))
|
||||
shown = spec.get('ref_only') or (([lead] if lead else []) + sprites)
|
||||
if spec.get('ref_only'): lead = None # ref_only sheets return exactly the frames asked for
|
||||
ref = ref_sheet(shown, f'{SCRATCH}/{name}_ref.png', spec.get('scale', 2.0))
|
||||
sheet = f'{SCRATCH}/{name}_hi.png'
|
||||
prompt = f"{spec['subject']} {STYLE}"
|
||||
if dry:
|
||||
@@ -106,12 +116,15 @@ def run(name, spec, dry=False):
|
||||
if lead: outs = outs[1:] # the scale reference is not installed
|
||||
before = [density(os.path.join(HERE, s + '.png')) for s in sprites]
|
||||
after = [density(o) for o in outs]
|
||||
# 1.25x, not 1.5x: a sheet that already has blood on it starts with a high edge density, so a
|
||||
# genuinely finer redraw of a wounded body scores a smaller gain than a clean one.
|
||||
if sum(after) / len(after) < sum(before) / len(before) * 1.25:
|
||||
# Two jobs, two bars. A coarse->fine REDRAW has to be measurably finer (1.25x, not 1.5x: a sheet
|
||||
# that already has blood on it starts high, so a genuinely finer wounded body gains less). A
|
||||
# REPOSE — turning the player around, pointing the runner at the camera, matching a wound between
|
||||
# two frames — is already fine art and only has to come back no worse.
|
||||
bar = 1.25 if spec.get('check', 'finer') == 'finer' else 0.85
|
||||
if sum(after) / len(after) < sum(before) / len(before) * bar:
|
||||
print(f'[{name}] REJECTED: not finer than what it replaces {before} -> {after}'); return False
|
||||
for o, s in zip(outs, sprites):
|
||||
colour_match(o, s)
|
||||
if spec.get('check', 'finer') == 'finer': colour_match(o, s)
|
||||
Image.open(o).save(os.path.join(HERE, s + '.png'))
|
||||
print(f'[{name}] installed. detail {before} -> {after}')
|
||||
return True
|
||||
|
||||
+77
-10
@@ -100,13 +100,12 @@
|
||||
"player_serve": {
|
||||
"sprites": [
|
||||
"p_toss",
|
||||
"p_smash",
|
||||
"p_swing1",
|
||||
"p_swing2"
|
||||
"p_smash"
|
||||
],
|
||||
"ref": "p_idle1",
|
||||
"anchor": 0,
|
||||
"subject": "Five frames of the same tennis player in a white shirt, blue shorts and a white headband, seen from BEHIND and slightly to the side, drawn as coarse low-resolution pixel art. First a plain standing frame for scale, then: tossing the ball up for a serve with the racket arm dropped back; the smash at full stretch with the racket overhead and both feet off the ground; and two frames of a forehand swing. In every frame he faces AWAY from the camera, up the court."
|
||||
"check": "same",
|
||||
"subject": "Three frames of the same tennis player in a white shirt, blue shorts and a white headband, seen from BEHIND and slightly to the side, drawn as coarse low-resolution pixel art. First a plain standing frame for scale, then: tossing the ball up for a serve with the racket arm dropped back; and the smash at full stretch with the racket overhead and both feet off the ground. In every frame he faces AWAY from the camera, up the court \u2014 the back of his head towards you, no face."
|
||||
},
|
||||
"player_run": {
|
||||
"sprites": [
|
||||
@@ -117,7 +116,8 @@
|
||||
],
|
||||
"ref": "p_idle1",
|
||||
"anchor": 0,
|
||||
"subject": "Five frames of the same tennis player in a white shirt and blue shorts, drawn as coarse low-resolution pixel art. Every figure is seen strictly FROM BEHIND \u2014 the back of his head and the back of his shirt face the viewer, no face, no eyes, no nose, he is running or standing AWAY from the camera. First a standing frame for scale, then a four-frame run cycle, running away from the camera with no racket."
|
||||
"subject": "Five frames of the same tennis player in a white shirt and blue shorts, drawn as coarse low-resolution pixel art. Every figure is seen strictly FROM BEHIND \u2014 the back of his head and the back of his shirt face the viewer, no face, no eyes, no nose, he is running or standing AWAY from the camera. First a standing frame for scale, then a four-frame run cycle, running away from the camera with no racket.",
|
||||
"check": "same"
|
||||
},
|
||||
"player_death": {
|
||||
"sprites": [
|
||||
@@ -241,9 +241,12 @@
|
||||
"p_bounce",
|
||||
"p_bounce2"
|
||||
],
|
||||
"ref": "p_run1",
|
||||
"ref_only": [
|
||||
"p_run1"
|
||||
],
|
||||
"anchor": 0,
|
||||
"subject": "Five frames of the same tennis player in a white shirt, blue shorts and a white headband, drawn as coarse low-resolution pixel art. Every figure is seen strictly FROM BEHIND \u2014 the back of his head and the back of his shirt face the viewer, no face, no eyes, no nose, he is running or standing AWAY from the camera. First a running frame for scale, then: two waiting stances holding a racket down at his side, and two frames of him bouncing a ball on the ground beside his LEFT foot before serving."
|
||||
"check": "same",
|
||||
"subject": "The reference is one tennis player in a white shirt, blue shorts and a white headband, seen FROM BEHIND. Draw FOUR frames of that same player, same size, same style. Every figure is drawn strictly FROM BEHIND like the reference: the back of his head and the back of his shirt face you, NO face, NO eyes, NO nose, NO mouth anywhere in the image. The four frames: (1) standing waiting, feet apart, racket held down at his right side; (2) the same stance with his weight shifted to the other foot; (3) bouncing a ball on the ground beside his right foot, leaning slightly down; (4) the same bounce a moment later, the ball higher. Output exactly four figures in one row."
|
||||
},
|
||||
"runner_front": {
|
||||
"sprites": [
|
||||
@@ -252,8 +255,12 @@
|
||||
"z_f3",
|
||||
"z_f4"
|
||||
],
|
||||
"ref_only": [
|
||||
"z_c1"
|
||||
],
|
||||
"anchor": 0,
|
||||
"subject": "Four frames of a lean SPRINTING zombie in a torn tracksuit, drawn as coarse low-resolution pixel art running side-on. Redraw the four frames as the same sprinting zombie CHARGING STRAIGHT AT THE VIEWER, down the court towards the camera \u2014 a front-facing run cycle: his face and chest towards you, one knee driving up towards the camera and the other leg trailing behind him, arms pumping across his body, the whole figure foreshortened as if he is bearing down on you. He must NOT be running sideways across the frame in any of them. Keep the torn tracksuit, the green skin, the same height."
|
||||
"check": "same",
|
||||
"subject": "The reference is one zombie drawn FACING THE VIEWER. Draw FOUR frames of a DIFFERENT zombie in that same front-facing style, same size: a lean SPRINTING zombie in a torn grey-green tracksuit, charging straight down the court AT THE VIEWER. In every frame his chest and face point at you and he is coming towards you, foreshortened \u2014 one knee driven up high towards the camera, the other leg trailing far behind, arms pumping across his chest, body leaning into the run. The four frames are four stages of that charge: left knee up, mid-air stretch, right knee up, mid-air stretch the other way. He must NEVER be running sideways across the frame. Torn tracksuit, exposed ribs, green skin, sunken eyes and teeth. Output exactly four figures in one row."
|
||||
},
|
||||
"brute_all_wounds": {
|
||||
"sprites": [
|
||||
@@ -263,7 +270,8 @@
|
||||
"z_gw2b"
|
||||
],
|
||||
"anchor": 0,
|
||||
"subject": "Four frames of the same enormous fat zombie brute, drawn as coarse low-resolution pixel art. The FIRST TWO are the same damage stage \u2014 his LEFT arm torn off at the shoulder leaving a ragged bloody stump, the right arm dragging a rusty pole \u2014 shown as two stages of one stride. The LAST TWO are the next damage stage, BOTH arms gone at the shoulders, again two stages of one stride. Within each pair the injuries must be IDENTICAL and on the same side of the body: only the legs change."
|
||||
"subject": "Four frames of the same enormous fat zombie brute, drawn as coarse low-resolution pixel art. The FIRST TWO are the same damage stage \u2014 his LEFT arm torn off at the shoulder leaving a ragged bloody stump, the right arm dragging a rusty pole \u2014 shown as two stages of one stride. The LAST TWO are the next damage stage, BOTH arms gone at the shoulders, again two stages of one stride. Within each pair the injuries must be IDENTICAL and on the same side of the body: only the legs change.",
|
||||
"check": "same"
|
||||
},
|
||||
"brute_all_wounds2": {
|
||||
"sprites": [
|
||||
@@ -273,6 +281,65 @@
|
||||
"z_gw4b"
|
||||
],
|
||||
"anchor": 0,
|
||||
"subject": "Four frames of the same enormous fat zombie brute, drawn as coarse low-resolution pixel art. The FIRST TWO are the same damage stage \u2014 chest and belly torn wide open with the ribs showing \u2014 as two stages of one stride. The LAST TWO are the final stage, HEADLESS with the ribs out, still standing, again two stages of one stride. Within each pair the injuries must be IDENTICAL and in the same place: only the legs change."
|
||||
"subject": "Four frames of the same enormous fat zombie brute, drawn as coarse low-resolution pixel art. The FIRST TWO are the same damage stage \u2014 chest and belly torn wide open with the ribs showing \u2014 as two stages of one stride. The LAST TWO are the final stage, HEADLESS with the ribs out, still standing, again two stages of one stride. Within each pair the injuries must be IDENTICAL and in the same place: only the legs change.",
|
||||
"check": "same"
|
||||
},
|
||||
"player_swing": {
|
||||
"sprites": [
|
||||
"p_swing1",
|
||||
"p_swing2"
|
||||
],
|
||||
"ref": "p_idle1",
|
||||
"anchor": 0,
|
||||
"check": "same",
|
||||
"subject": "Three frames of the same tennis player in a white shirt, blue shorts and a white headband, seen from BEHIND, drawn as coarse low-resolution pixel art. First a plain standing frame for scale, then two frames of a forehand swing \u2014 racket drawn back across the body, then followed through. In both he faces AWAY from the camera, up the court \u2014 the back of his head towards you, no face."
|
||||
},
|
||||
"brute_w1": {
|
||||
"sprites": [
|
||||
"z_gw",
|
||||
"z_gwb"
|
||||
],
|
||||
"ref_only": [
|
||||
"z_gw"
|
||||
],
|
||||
"anchor": 0,
|
||||
"check": "same",
|
||||
"subject": "The reference is one enormous fat zombie brute with his LEFT arm torn off at the shoulder leaving a ragged bloody stump, the right hand dragging a rusty pole. Draw TWO frames of that EXACT same body \u2014 same injury, on the SAME side, same clothes, same size, same facing \u2014 as two stages of one stride: the first with his left leg forward and right leg back, the second with the legs swapped and his weight sunk lower. The injury must be pixel-identical in both frames; ONLY the legs and the lean change. Output exactly two figures in one row."
|
||||
},
|
||||
"brute_w2": {
|
||||
"sprites": [
|
||||
"z_gw2",
|
||||
"z_gw2b"
|
||||
],
|
||||
"ref_only": [
|
||||
"z_gw2"
|
||||
],
|
||||
"anchor": 0,
|
||||
"check": "same",
|
||||
"subject": "The reference is one enormous fat zombie brute with BOTH arms torn off at the shoulders, two ragged bloody stumps. Draw TWO frames of that EXACT same body \u2014 same injury, on the SAME side, same clothes, same size, same facing \u2014 as two stages of one stride: the first with his left leg forward and right leg back, the second with the legs swapped and his weight sunk lower. The injury must be pixel-identical in both frames; ONLY the legs and the lean change. Output exactly two figures in one row."
|
||||
},
|
||||
"brute_w3": {
|
||||
"sprites": [
|
||||
"z_gw3",
|
||||
"z_gw3b"
|
||||
],
|
||||
"ref_only": [
|
||||
"z_gw3"
|
||||
],
|
||||
"anchor": 0,
|
||||
"check": "same",
|
||||
"subject": "The reference is one enormous fat zombie brute with his chest and belly torn wide open with the ribs showing through. Draw TWO frames of that EXACT same body \u2014 same injury, on the SAME side, same clothes, same size, same facing \u2014 as two stages of one stride: the first with his left leg forward and right leg back, the second with the legs swapped and his weight sunk lower. The injury must be pixel-identical in both frames; ONLY the legs and the lean change. Output exactly two figures in one row."
|
||||
},
|
||||
"brute_w4": {
|
||||
"sprites": [
|
||||
"z_gw4",
|
||||
"z_gw4b"
|
||||
],
|
||||
"ref_only": [
|
||||
"z_gw4"
|
||||
],
|
||||
"anchor": 0,
|
||||
"check": "same",
|
||||
"subject": "The reference is one enormous fat zombie brute with HEADLESS, a ragged neck stump, ribs out, still standing. Draw TWO frames of that EXACT same body \u2014 same injury, on the SAME side, same clothes, same size, same facing \u2014 as two stages of one stride: the first with his left leg forward and right leg back, the second with the legs swapped and his weight sunk lower. The injury must be pixel-identical in both frames; ONLY the legs and the lean change. Output exactly two figures in one row."
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
Reference in new issue
Block a user