Fix visual-style blur with an anti-blur focus
The style recipe's strong-blur prep is its structure-safety guarantee, but the encoder was also studying the blur itself - on soft-medium references renders came out pervasively soft. The built-in style bundle now ships a focus that de-selects softness and scene layout; prep and pulls are unchanged. A/B render-verified across five references, two strengths, three seeds, single-card and in the two-card method. Crisper prep alternatives re-opened source-scene takeover and were rejected.
This commit is contained in:
@@ -155,6 +155,13 @@ changed):
|
||||
guarantees. Keep `subject: avoid` and the treatment appropriate to the job,
|
||||
and render-validate like everything else.
|
||||
|
||||
- **De-selection also fixes prep artifacts:** the built-in `suggest the
|
||||
visual style` recipe ships a focus ending in "*not the image's blurriness
|
||||
or soft focus, and not its subject or scene layout*" - its strong-blur
|
||||
prep is the safety guarantee, and the focus stops that deliberate blur
|
||||
from being studied as if it were the style. Copy the pattern if your own
|
||||
heavy-treatment recipe starts echoing its treatment in renders.
|
||||
|
||||
## The `layers` Array, Exactly
|
||||
|
||||
### What the 12 positions are
|
||||
|
||||
@@ -365,8 +365,8 @@ Caveat: reuse assumes the connected CLIP's behavior is unchanged — pick
|
||||
|
||||
### 8.1 Built-in quick recipes (the shipped values)
|
||||
|
||||
All fourteen keys per bundle; `layers` refers to the family tables in §8.2.
|
||||
Values are the 2026-07 render-retuned set.
|
||||
All fourteen core keys per bundle; `layers` refers to the family tables in
|
||||
§8.2. Values are the 2026-07 render-retuned set.
|
||||
|
||||
| Recipe (dropdown label) | role | treatment | color | detail | study | framing | subject | early | late | cap | shape | global* | layers |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
@@ -386,6 +386,17 @@ Values are the 2026-07 render-retuned set.
|
||||
\* `global` is inert on Krea 2 (§2.1); values are kept for pooled-emitting
|
||||
encoders.
|
||||
|
||||
`suggest the visual style` additionally ships a `focus` (§9): *"the artistic
|
||||
style: palette, medium, brushwork, art direction, and rendering finish - not
|
||||
the image's blurriness or soft focus, and not its subject or scene layout"*.
|
||||
The strong-blur prep is the recipe's structure-safety guarantee, but without
|
||||
the focus the encoder also studied the blur itself - on soft-medium
|
||||
references (watercolor, gouache, aged photos) renders came out pervasively
|
||||
soft. De-selecting softness and layout at the instruction channel keeps the
|
||||
prompt subject crisp and primary while the medium still arrives
|
||||
(A/B render-verified 2026-07-06; crisper prep instead re-opened source-scene
|
||||
takeover).
|
||||
|
||||
Role pull baselines (used by manual mode and as defaults for minimal custom
|
||||
recipes): balanced 1.0/1.0, identity 1.0/1.0, style 0.8/1.35, palette
|
||||
0.7/1.75, composition 1.25/0.35, framing 0.9/0.25, environment 0.7/0.8,
|
||||
@@ -547,8 +558,9 @@ of a fox" at strength 1.0.*
|
||||
2. **Feel curve** (§3): σ = 0.65^1.6 = 0.5014.
|
||||
3. **Preparation** (§4): ≈384² px, full color, strong blur, and reduced
|
||||
small-detail study. The encoder sees softened medium and finish cues.
|
||||
4. **Prompt** (§5): system prompt gains the style role line and the avoid
|
||||
subject rule; user turn is one image-pad line plus the prompt.
|
||||
4. **Prompt** (§5): system prompt gains the style role line, the recipe's
|
||||
anti-blur focus line (§8.1), and the avoid subject rule; user turn is one
|
||||
image-pad line plus the prompt.
|
||||
5. **Targets** (§3), both phases (m = 0.85): base = 0.5014 × 0.85 =
|
||||
0.4262; token t = 0.4262 × 0.85 = **0.3623**; pooled g = 0.4262 × 1.85 =
|
||||
0.7885 (inert on Krea 2).
|
||||
|
||||
@@ -396,6 +396,14 @@ guarantees - keep `subject: avoid` and a job-appropriate treatment, and
|
||||
render-check like everything else. The stack report prints each card's
|
||||
focus so you can confirm it reached the encoder.
|
||||
|
||||
One built-in uses it too: `suggest the visual style` ships an anti-blur
|
||||
focus ("...not the image's blurriness or soft focus, and not its subject or
|
||||
scene layout"). The recipe softens the reference before study on purpose -
|
||||
that is its safety guarantee - and the focus keeps that deliberate blur from
|
||||
being read back as the style, so subjects stay crisp while the palette,
|
||||
medium, and brushwork arrive. You will see it on the card's stack-report
|
||||
line; that is expected.
|
||||
|
||||
A complete example (the shipped template - render-validated values):
|
||||
|
||||
```yaml
|
||||
@@ -782,6 +790,7 @@ If a loaded demo reports missing images, copy
|
||||
| Away card makes the image muddy or empty. | Lower its strength below `0.30`, and make sure something positive (prompt or toward card) says what you *do* want. |
|
||||
| Many cards fight each other. | Turn on `gentle balance`, or lower the two strongest cards. The report shows the applied scale. |
|
||||
| Style card drags its subject in. | Check the prepared-references preview; if the subject is visible there, lower detail or strengthen the treatment. In manual mode, lower `Structure layers pull`. |
|
||||
| Style results look soft or out of focus. | Make sure you are on the current tuning: `suggest the visual style` ships an anti-blur focus (printed on its stack-report line) that stops the recipe's deliberate reference-softening from being copied as the style. If soft-medium references (watercolor, hazy photos) still read soft, that is the medium arriving - lower the card below `0.6` or add crispness words to the prompt. |
|
||||
| Re-runs are slow while tuning. | Set `Reuse image studies` to `reuse between runs` and keep the prompt fixed while you tune strengths. |
|
||||
| Behaves oddly after swapping CLIP patches. | Use `always re-study` while experimenting with CLIP-side changes. |
|
||||
|
||||
|
||||
@@ -24,6 +24,14 @@ class _V9Resolution(_V9Card):
|
||||
|
||||
QUICK_RECIPES = recipes.QUICK_RECIPES
|
||||
|
||||
@classmethod
|
||||
def _recipe_settings(cls, recipe_key):
|
||||
# V9's resolver predates the focus field and drops unknown bundle
|
||||
# keys, so a V10 built-in recipe's focus is forwarded here.
|
||||
settings = super()._recipe_settings(recipe_key)
|
||||
settings["focus"] = cls.QUICK_RECIPES[recipe_key].get("focus", "")
|
||||
return settings
|
||||
|
||||
|
||||
class KGKrea2ImageGuideCardV10:
|
||||
"""
|
||||
|
||||
@@ -22,6 +22,22 @@ LIGHTING_LAYER_PULL = _v9_recipes.LIGHTING_LAYER_PULL
|
||||
STYLE_TRANSFER_LAYER_PULL = [0.062, 0.087, 0.113, 0.15, 0.2, 0.25, 1.25, 3.438, 6.875, 1.375, 5.5, 1.5]
|
||||
MATERIAL_FINISH_LAYER_PULL = [0.05, 0.075, 0.113, 0.163, 0.213, 0.25, 1.25, 2.75, 5.5, 1.5, 4.125, 1.375]
|
||||
|
||||
# Render-tuned 2026-07-06: the strong-blur prep is the style recipe's
|
||||
# structure-safety guarantee, but the encoder was also *studying the blur* -
|
||||
# on soft-medium references (watercolor, gouache, aged photos) renders came
|
||||
# out pervasively soft, with the subject small and hazy. Crisper prep
|
||||
# (higher detail, larger study) re-opened source-scene takeover instead, so
|
||||
# the correction rides the instruction channel: de-selecting softness and
|
||||
# scene layout keeps the prompt subject crisp and primary while palette,
|
||||
# medium, and brushwork still arrive. A/B render-verified across five
|
||||
# references, two strengths, and three seeds, single-card and in the
|
||||
# two-card style-transfer method.
|
||||
STYLE_TRANSFER_FOCUS = (
|
||||
"the artistic style: palette, medium, brushwork, art direction, and "
|
||||
"rendering finish - not the image's blurriness or soft focus, and not "
|
||||
"its subject or scene layout"
|
||||
)
|
||||
|
||||
role_pull_defaults = _v9_recipes.role_pull_defaults
|
||||
role_layer_pull_defaults = _v9_recipes.role_layer_pull_defaults
|
||||
effective_image_strength = _v9_recipes.effective_image_strength
|
||||
@@ -52,6 +68,7 @@ QUICK_RECIPES.update({
|
||||
"shape": 0.85,
|
||||
"global": 1.85,
|
||||
"layers": STYLE_TRANSFER_LAYER_PULL,
|
||||
"focus": STYLE_TRANSFER_FOCUS,
|
||||
},
|
||||
"texture gentle": {
|
||||
"role": "material",
|
||||
|
||||
+16
-5
@@ -252,9 +252,13 @@ class KreaV10LabelContractTests(unittest.TestCase):
|
||||
):
|
||||
self.assertIn(key, recipes)
|
||||
self.assertEqual(recipes[key]["role"], role)
|
||||
# Every recipe (V9 and V10) carries the full settings bundle.
|
||||
# Every recipe (V9 and V10) carries the full settings bundle;
|
||||
# `focus` is the only optional extra a bundle may add.
|
||||
for key, recipe in recipes.items():
|
||||
self.assertEqual(set(recipe.keys()), RECIPE_KEYS, "recipe {} is incomplete".format(key))
|
||||
self.assertEqual(
|
||||
set(recipe.keys()) - {"focus"}, RECIPE_KEYS,
|
||||
"recipe {} is incomplete".format(key),
|
||||
)
|
||||
|
||||
def test_v10_max_layer_scale_constant(self):
|
||||
self.assertEqual(self.nodes.KGTextEncodeKreaImageReferencesV10.MAX_LAYER_SCALE, 6.0)
|
||||
@@ -303,7 +307,11 @@ class KreaV10CardBehaviorTests(unittest.TestCase):
|
||||
self.assertGreater(card["resolved_shape_pull"], 0.4)
|
||||
self.assertAlmostEqual(card["resolved_global_pull"], 1.85)
|
||||
self.assertEqual(card["resolved_layer_pull"], self.nodes.recipes.STYLE_TRANSFER_LAYER_PULL)
|
||||
self.assertEqual(card["resolved_focus"], "")
|
||||
# Anti-blur focus (2026-07-06): the strong-blur prep must not itself
|
||||
# be studied as the style.
|
||||
self.assertEqual(card["resolved_focus"], self.nodes.recipes.STYLE_TRANSFER_FOCUS)
|
||||
self.assertIn("not the image's blurriness", card["resolved_focus"])
|
||||
self.assertEqual(card["focus"], self.nodes.recipes.STYLE_TRANSFER_FOCUS)
|
||||
self.assertEqual(card["resolved_direction"], "toward")
|
||||
self.assertEqual(card["resolved_timing"], "recipe")
|
||||
|
||||
@@ -766,9 +774,12 @@ class KreaV10CustomRecipeTests(unittest.TestCase):
|
||||
card = self._build("clothing borrower")
|
||||
self.assertEqual(card["resolved_focus"], "the clothing and garment style, not the person")
|
||||
self.assertEqual(card["focus"], "the clothing and garment style, not the person")
|
||||
# Built-in recipes carry an empty focus (key present, no text).
|
||||
builtin = self._build("suggest the visual style")
|
||||
# Built-in recipes without a focus carry an empty one (key present,
|
||||
# no text); the V10 style recipe ships its anti-blur focus.
|
||||
builtin = self._build("suggest the color palette")
|
||||
self.assertEqual(builtin["resolved_focus"], "")
|
||||
style = self._build("suggest the visual style")
|
||||
self.assertEqual(style["resolved_focus"], self.nodes.recipes.STYLE_TRANSFER_FOCUS)
|
||||
|
||||
def test_focus_without_text_is_omitted_from_the_bundle(self):
|
||||
self._write("nofocus.json", json.dumps({"label": "plain style", "role": "style", "focus": " "}))
|
||||
|
||||
Reference in New Issue
Block a user