Spaces:
Running on Zero
Running on Zero
Reject non-studio cutout attempts
Browse files
README.md
CHANGED
|
@@ -67,7 +67,7 @@ If a requested asset has no deterministic hook, images are still generated for r
|
|
| 67 |
|
| 68 |
## Contract-driven generation and validation
|
| 69 |
|
| 70 |
-
Filenames and IDs do not decide whether an image is a scene or sprite. Dimensions, transparency, composition, camera, quantity, subject count, and silhouette requirements come from the manifest. Transparent single-subject outputs receive alpha extraction, occupancy normalization, subject-count checks, and a retained-scene check that rejects environmental foreground spread around an isolated subject. Opaque outputs are checked for unwanted transparency. Seamless requests receive an opposite-edge similarity check. Other compositions are not incorrectly rejected for containing multiple subjects.
|
| 71 |
|
| 72 |
The image model can still violate these instructions, so every result requires visual review. Single-subject outputs that fail automated checks are regenerated with a fresh seed rather than cropped into a guessed subject. The review UI can regenerate one output or a complete multi-output asset set.
|
| 73 |
|
|
@@ -89,7 +89,7 @@ segmind/SSD-1B + latent-consistency/lcm-lora-ssd-1b
|
|
| 89 |
|
| 90 |
SSD-1B is an Apache-2.0 distilled SDXL model. The LCM adapter enables low-step generation. The weights run inside the Space's ZeroGPU allocation, so the app does not consume Hugging Face Inference Provider credits and does not require a paid image API.
|
| 91 |
|
| 92 |
-
Sprites and backgrounds are generated directly from their written prompts. No procedurally drawn sprite, palette, silhouette, camera guide, or background layout is passed into the production model. Sprite prompts use a portrait canvas and positive single-subject composition language; the negative prompt separately rejects sheets, lineups, repeated subjects, multiple views, and surrounding environments. After transparency extraction, sprites with zero or multiple significant foreground components, retained scene-like alpha, implausible silhouettes, or inadequate scale are regenerated with a new seed up to `PRIMARY_SPRITE_ATTEMPTS` times. If every attempt fails, the deployed Space returns an explicit model-generation error rather than returning a contact sheet or environment-contaminated cutout. Background negative prompts reject characters and generic particle overlays.
|
| 93 |
|
| 94 |
SSD-1B's CLIP text encoder has a 77-token context window. Production prompts therefore use a conservative word budget, place the camera and single-subject contract first, and compact the free-form description. This prevents those critical constraints from being silently truncated behind verbose style text.
|
| 95 |
|
|
|
|
| 67 |
|
| 68 |
## Contract-driven generation and validation
|
| 69 |
|
| 70 |
+
Filenames and IDs do not decide whether an image is a scene or sprite. Dimensions, transparency, composition, camera, quantity, subject count, and silhouette requirements come from the manifest. Transparent single-subject outputs must first arrive from the model on a plain light studio field; scene-like model frames are rejected before alpha extraction. Passing outputs then receive alpha extraction, occupancy normalization, subject-count checks, and a retained-scene check that rejects environmental foreground spread around an isolated subject. Opaque outputs are checked for unwanted transparency. Seamless requests receive an opposite-edge similarity check. Other compositions are not incorrectly rejected for containing multiple subjects.
|
| 71 |
|
| 72 |
The image model can still violate these instructions, so every result requires visual review. Single-subject outputs that fail automated checks are regenerated with a fresh seed rather than cropped into a guessed subject. The review UI can regenerate one output or a complete multi-output asset set.
|
| 73 |
|
|
|
|
| 89 |
|
| 90 |
SSD-1B is an Apache-2.0 distilled SDXL model. The LCM adapter enables low-step generation. The weights run inside the Space's ZeroGPU allocation, so the app does not consume Hugging Face Inference Provider credits and does not require a paid image API.
|
| 91 |
|
| 92 |
+
Sprites and backgrounds are generated directly from their written prompts. No procedurally drawn sprite, palette, silhouette, camera guide, or background layout is passed into the production model. Sprite prompts use a portrait canvas and positive single-subject composition language; the negative prompt separately rejects sheets, lineups, repeated subjects, multiple views, and surrounding environments. Before alpha extraction, cutout attempts whose boundary is not predominantly light and neutral are rejected because they did not honor the requested studio field. After transparency extraction, sprites with zero or multiple significant foreground components, retained scene-like alpha, implausible silhouettes, or inadequate scale are regenerated with a new seed up to `PRIMARY_SPRITE_ATTEMPTS` times. If every attempt fails, the deployed Space returns an explicit model-generation error rather than returning a contact sheet or environment-contaminated cutout. Background negative prompts reject characters and generic particle overlays.
|
| 93 |
|
| 94 |
SSD-1B's CLIP text encoder has a 77-token context window. Production prompts therefore use a conservative word budget, place the camera and single-subject contract first, and compact the free-form description. This prevents those critical constraints from being silently truncated behind verbose style text.
|
| 95 |
|
app.py
CHANGED
|
@@ -2016,6 +2016,9 @@ def primary_diffusion_png(spec: AssetSpec, index: int, run_id: int) -> tuple[byt
|
|
| 2016 |
width=width,
|
| 2017 |
height=height,
|
| 2018 |
).images[0]
|
|
|
|
|
|
|
|
|
|
| 2019 |
content = polish_diffusion_asset(image, spec)
|
| 2020 |
if is_background:
|
| 2021 |
return content, None
|
|
@@ -2145,6 +2148,30 @@ def polish_diffusion_asset(image: Image.Image, spec: AssetSpec) -> bytes:
|
|
| 2145 |
return out.getvalue()
|
| 2146 |
|
| 2147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2148 |
def foreground_component_geometry_from_image(image: Image.Image) -> list[tuple[int, tuple[int, int, int, int]]]:
|
| 2149 |
"""Return alpha-component areas and bounding boxes for an RGBA image, largest first."""
|
| 2150 |
image = image.convert("RGBA")
|
|
@@ -2810,7 +2837,7 @@ def model_configuration_summary() -> str:
|
|
| 2810 |
f"neural enforcement: `{enforcement}` 路 primary readiness: `{readiness}`. "
|
| 2811 |
"Every production image is generated directly from its written prompt by the primary text-to-image model. "
|
| 2812 |
"The user-defined composition and camera contract is placed first inside a conservative CLIP prompt budget. "
|
| 2813 |
-
"Transparent single-subject
|
| 2814 |
"retained-scene, silhouette, and scale validation; failures are regenerated with a new seed up to "
|
| 2815 |
f"{PRIMARY_SPRITE_ATTEMPTS} times. No procedural guide is supplied to the model. The procedural renderer is "
|
| 2816 |
"development-only and is blocked in the deployed Space when the primary model fails."
|
|
|
|
| 2016 |
width=width,
|
| 2017 |
height=height,
|
| 2018 |
).images[0]
|
| 2019 |
+
if not is_background and has_invalid_cutout_studio_field(image):
|
| 2020 |
+
last_failure_detail = "the last output did not use the required plain light studio field"
|
| 2021 |
+
continue
|
| 2022 |
content = polish_diffusion_asset(image, spec)
|
| 2023 |
if is_background:
|
| 2024 |
return content, None
|
|
|
|
| 2148 |
return out.getvalue()
|
| 2149 |
|
| 2150 |
|
| 2151 |
+
def has_invalid_cutout_studio_field(image: Image.Image) -> bool:
|
| 2152 |
+
"""Reject model scenes before alpha extraction when their outer field is not light and neutral.
|
| 2153 |
+
|
| 2154 |
+
Transparent cutouts are prompted on a plain white studio field. When SSD-1B
|
| 2155 |
+
instead puts foliage or another environment at the image boundary, the old
|
| 2156 |
+
corner-color extraction treated that scenery as the background and preserved
|
| 2157 |
+
the scene's lighter interior. Validate the model image itself so a new model
|
| 2158 |
+
attempt is requested before any transparency or scale post-processing.
|
| 2159 |
+
"""
|
| 2160 |
+
sample = image.convert("RGB").resize((64, 64), Image.LANCZOS)
|
| 2161 |
+
band = 5
|
| 2162 |
+
edge_pixels = []
|
| 2163 |
+
for y in range(64):
|
| 2164 |
+
for x in range(64):
|
| 2165 |
+
if x < band or x >= 64 - band or y < band or y >= 64 - band:
|
| 2166 |
+
edge_pixels.append(sample.getpixel((x, y)))
|
| 2167 |
+
|
| 2168 |
+
light_neutral = sum(
|
| 2169 |
+
min(pixel) >= 180 and max(pixel) - min(pixel) <= 70
|
| 2170 |
+
for pixel in edge_pixels
|
| 2171 |
+
)
|
| 2172 |
+
return light_neutral / max(1, len(edge_pixels)) < 0.72
|
| 2173 |
+
|
| 2174 |
+
|
| 2175 |
def foreground_component_geometry_from_image(image: Image.Image) -> list[tuple[int, tuple[int, int, int, int]]]:
|
| 2176 |
"""Return alpha-component areas and bounding boxes for an RGBA image, largest first."""
|
| 2177 |
image = image.convert("RGBA")
|
|
|
|
| 2837 |
f"neural enforcement: `{enforcement}` 路 primary readiness: `{readiness}`. "
|
| 2838 |
"Every production image is generated directly from its written prompt by the primary text-to-image model. "
|
| 2839 |
"The user-defined composition and camera contract is placed first inside a conservative CLIP prompt budget. "
|
| 2840 |
+
"Transparent single-subject attempts must first honor the light studio-field contract, are normalized to the requested canvas, then pass configured subject-count, "
|
| 2841 |
"retained-scene, silhouette, and scale validation; failures are regenerated with a new seed up to "
|
| 2842 |
f"{PRIMARY_SPRITE_ATTEMPTS} times. No procedural guide is supplied to the model. The procedural renderer is "
|
| 2843 |
"development-only and is blocked in the deployed Space when the primary model fails."
|