LeafCat79 commited on
Commit
4a5615c
·
verified ·
1 Parent(s): 22df65e

Reject incompatible overhead silhouettes

Browse files
Files changed (1) hide show
  1. app.py +32 -32
app.py CHANGED
@@ -1947,8 +1947,8 @@ def neural_foreground_cutout(image: Image.Image) -> Image.Image:
1947
  return cutout
1948
 
1949
 
1950
- def top_down_subject_contract(spec: AssetSpec) -> str:
1951
- """Describe visible overhead anatomy without drawing or reshaping model artwork."""
1952
  # Classify only from the user's visual description. Custom IDs such as
1953
  # ``player`` or ``enemy`` are integration hooks, not reliable anatomy.
1954
  description = f"{spec.description} {spec.prompt}".lower()
@@ -1985,16 +1985,28 @@ def top_down_subject_contract(spec: AssetSpec) -> str:
1985
  )
1986
 
1987
  if contains_any_term(description, radial_terms):
 
 
 
 
 
 
 
 
 
 
 
 
1988
  return (
1989
  "Top of body dominates; splayed limbs radiate in image plane; "
1990
  "no upright torso or side elevation."
1991
  )
1992
- if contains_any_term(description, vehicle_terms):
1993
  return (
1994
  "Roof and chassis top dominate; wheel footprints flank both sides; "
1995
  "no grille or side elevation."
1996
  )
1997
- if spec.silhouette == "humanoid" or contains_any_term(description, humanoid_terms):
1998
  return (
1999
  "Full body overhead: head crown, shoulders and back visible; "
2000
  "face and chest invisible; limbs foreshortened."
@@ -2120,7 +2132,7 @@ def primary_diffusion_png(spec: AssetSpec, index: int, run_id: int) -> tuple[byt
2120
  continue
2121
  if has_front_view_like_top_down_silhouette(content, spec):
2122
  last_failure_detail = (
2123
- "the last output retained a tall portrait-like silhouette instead of the requested overhead view"
2124
  )
2125
  continue
2126
  if has_undersized_foreground_subject(content):
@@ -2467,13 +2479,13 @@ def has_implausibly_thin_foreground_subject(content: bytes, spec: AssetSpec) ->
2467
 
2468
 
2469
  def has_front_view_like_top_down_silhouette(content: bytes, spec: AssetSpec) -> bool:
2470
- """Conservatively reject upright portrait silhouettes for overhead sprite contracts.
2471
 
2472
- Alpha geometry cannot prove camera perspective, but a tall, canvas-filling
2473
- humanoid is a strong signal that the generator ignored an overhead request.
2474
- Broader non-humanoid checks apply only when the user's own description asks
2475
- for a radial, wide, or multi-legged body. Narrow top-down props and vehicles
2476
- therefore remain valid user-configurable assets.
2477
  """
2478
  if spec.camera != "top_down" or spec.composition not in {"single_subject", "icon", "animation_frame"}:
2479
  return False
@@ -2491,31 +2503,19 @@ def has_front_view_like_top_down_silhouette(content: bytes, spec: AssetSpec) ->
2491
  if height_ratio < 0.72:
2492
  return False
2493
 
2494
- if spec.silhouette == "humanoid" and aspect >= 1.35:
 
 
 
 
2495
  return True
2496
 
2497
  description = f"{spec.description} {spec.prompt}"
2498
- broad_shape_requested = contains_any_term(
2499
  description,
2500
- (
2501
- "broad",
2502
- "radial",
2503
- "wide-bodied",
2504
- "wide bodied",
2505
- "six-legged",
2506
- "six legged",
2507
- "four-legged",
2508
- "four legged",
2509
- "multi-legged",
2510
- "multi legged",
2511
- "quadruped",
2512
- "spider-like",
2513
- "spider like",
2514
- "crab-like",
2515
- "crab like",
2516
- ),
2517
  )
2518
- if broad_shape_requested and aspect >= 1.45:
2519
  return True
2520
 
2521
  narrow_subject_requested = contains_any_term(
@@ -2840,7 +2840,7 @@ def validate_asset_png(content: bytes, spec: AssetSpec) -> list[str]:
2840
  elif spec.expected_subjects == 1 and has_implausibly_thin_foreground_subject(content, spec):
2841
  warnings.append("sprite foreground silhouette is implausibly thin")
2842
  elif spec.expected_subjects == 1 and has_front_view_like_top_down_silhouette(content, spec):
2843
- warnings.append("top-down sprite silhouette remains strongly portrait-like")
2844
  elif spec.expected_subjects == 1 and has_undersized_foreground_subject(content):
2845
  warnings.append("foreground subject occupies too little of the output canvas")
2846
  if spec.composition == "seamless" and image.width > 1 and image.height > 1:
 
1947
  return cutout
1948
 
1949
 
1950
+ def infer_top_down_subject_geometry(spec: AssetSpec) -> str:
1951
+ """Infer an overhead footprint from user-authored visual terms, never the asset ID."""
1952
  # Classify only from the user's visual description. Custom IDs such as
1953
  # ``player`` or ``enemy`` are integration hooks, not reliable anatomy.
1954
  description = f"{spec.description} {spec.prompt}".lower()
 
1985
  )
1986
 
1987
  if contains_any_term(description, radial_terms):
1988
+ return "radial"
1989
+ if contains_any_term(description, vehicle_terms):
1990
+ return "vehicle"
1991
+ if spec.silhouette == "humanoid" or contains_any_term(description, humanoid_terms):
1992
+ return "humanoid"
1993
+ return "generic"
1994
+
1995
+
1996
+ def top_down_subject_contract(spec: AssetSpec) -> str:
1997
+ """Describe visible overhead anatomy without drawing or reshaping model artwork."""
1998
+ geometry = infer_top_down_subject_geometry(spec)
1999
+ if geometry == "radial":
2000
  return (
2001
  "Top of body dominates; splayed limbs radiate in image plane; "
2002
  "no upright torso or side elevation."
2003
  )
2004
+ if geometry == "vehicle":
2005
  return (
2006
  "Roof and chassis top dominate; wheel footprints flank both sides; "
2007
  "no grille or side elevation."
2008
  )
2009
+ if geometry == "humanoid":
2010
  return (
2011
  "Full body overhead: head crown, shoulders and back visible; "
2012
  "face and chest invisible; limbs foreshortened."
 
2132
  continue
2133
  if has_front_view_like_top_down_silhouette(content, spec):
2134
  last_failure_detail = (
2135
+ "the last output silhouette conflicted with the requested overhead body footprint"
2136
  )
2137
  continue
2138
  if has_undersized_foreground_subject(content):
 
2479
 
2480
 
2481
  def has_front_view_like_top_down_silhouette(content: bytes, spec: AssetSpec) -> bool:
2482
+ """Reject silhouettes that contradict a requested overhead body footprint.
2483
 
2484
+ Alpha geometry cannot prove camera perspective. It can, however, fail closed
2485
+ when a normalized, canvas-filling silhouette contradicts explicit user terms:
2486
+ compact humanoids cannot remain upright portraits; radial bodies must not be
2487
+ taller than wide; and explicitly wide vehicles must present a wide footprint.
2488
+ Narrow props remain exempt.
2489
  """
2490
  if spec.camera != "top_down" or spec.composition not in {"single_subject", "icon", "animation_frame"}:
2491
  return False
 
2503
  if height_ratio < 0.72:
2504
  return False
2505
 
2506
+ geometry = infer_top_down_subject_geometry(spec)
2507
+ if geometry == "humanoid" and aspect >= 1.10:
2508
+ return True
2509
+
2510
+ if geometry == "radial" and aspect >= 1.02:
2511
  return True
2512
 
2513
  description = f"{spec.description} {spec.prompt}"
2514
+ explicitly_wide_vehicle = geometry == "vehicle" and contains_any_term(
2515
  description,
2516
+ ("wide", "four-wheel", "four wheel", "six-wheel", "six wheel", "tracked"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2517
  )
2518
+ if explicitly_wide_vehicle and aspect >= 0.95:
2519
  return True
2520
 
2521
  narrow_subject_requested = contains_any_term(
 
2840
  elif spec.expected_subjects == 1 and has_implausibly_thin_foreground_subject(content, spec):
2841
  warnings.append("sprite foreground silhouette is implausibly thin")
2842
  elif spec.expected_subjects == 1 and has_front_view_like_top_down_silhouette(content, spec):
2843
+ warnings.append("top-down sprite silhouette conflicts with the requested overhead footprint")
2844
  elif spec.expected_subjects == 1 and has_undersized_foreground_subject(content):
2845
  warnings.append("foreground subject occupies too little of the output canvas")
2846
  if spec.composition == "seamless" and image.width > 1 and image.height > 1: