Simplify to single-segmenter pipelines; add screen_color prior; drop rescue + recolor
Strategic pivot: the dropout-fill rescue, the anime-seg fill backend, the
BiRefNet+anime-seg intersection, and the recolor pass all existed to repair
source images whose hair was already green-contaminated or broken at generation
time. Fixing the source instead (clean pastel-background generation) makes the
matte high-contrast, so that whole compensation layer is unnecessary. Remove it.
- Two pipelines via segmentation.enabled:
false -> chroma-only (Chroma + ViTMatte)
true -> single segmenter (default anime-seg, switchable birefnet) -> trimap
then ViTMatte refines, pymatting estimates foreground, despill cleans spill.
- Generalise the green-hardcoded colour logic to a screen_color prior (hex, e.g.
"#CFEFFF"; default null = green auto-detect, byte-identical). chroma keys off
Lab/RGB distance to the colour; despill removes chroma along its Lab direction.
Added --screen-color CLI flag.
- Removed dead code: fill_seg_dropouts + seg_fill*/intersection params,
SegmentationSettings.fill_backend/fill_model_name/sharpen, unsharp_mask,
recolor.py + RecolorSettings.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+10
-5
@@ -11,7 +11,6 @@ from .settings import (
|
||||
ForegroundSettings,
|
||||
ModelSettings,
|
||||
PipelineSettings,
|
||||
RecolorSettings,
|
||||
SegmentationSettings,
|
||||
TrimapSettings,
|
||||
)
|
||||
@@ -44,7 +43,9 @@ def _update_dataclass(instance: T, values: dict[str, Any] | None) -> T:
|
||||
|
||||
|
||||
def settings_from_dict(data: dict[str, Any]) -> PipelineSettings:
|
||||
allowed_sections = {"chroma", "trimap", "alpha_post", "foreground", "despill", "recolor", "model", "segmentation"}
|
||||
data = dict(data)
|
||||
screen_color = data.pop("screen_color", None)
|
||||
allowed_sections = {"chroma", "trimap", "alpha_post", "foreground", "despill", "model", "segmentation"}
|
||||
unknown_sections = sorted(set(data) - allowed_sections)
|
||||
if unknown_sections:
|
||||
raise ValueError(f"Unknown config section(s): {', '.join(unknown_sections)}")
|
||||
@@ -55,9 +56,9 @@ def settings_from_dict(data: dict[str, Any]) -> PipelineSettings:
|
||||
alpha_post=_update_dataclass(AlphaPostSettings(), data.get("alpha_post")),
|
||||
foreground=_update_dataclass(ForegroundSettings(), data.get("foreground")),
|
||||
despill=_update_dataclass(DespillSettings(), data.get("despill")),
|
||||
recolor=_update_dataclass(RecolorSettings(), data.get("recolor")),
|
||||
model=_update_dataclass(ModelSettings(), data.get("model")),
|
||||
segmentation=_update_dataclass(SegmentationSettings(), data.get("segmentation")),
|
||||
screen_color=screen_color,
|
||||
)
|
||||
|
||||
|
||||
@@ -73,7 +74,6 @@ def override_settings(settings: PipelineSettings, **overrides: Any) -> PipelineS
|
||||
alpha_post = settings.alpha_post
|
||||
foreground = settings.foreground
|
||||
despill = settings.despill
|
||||
recolor = settings.recolor
|
||||
model = settings.model
|
||||
segmentation = settings.segmentation
|
||||
|
||||
@@ -99,13 +99,18 @@ def override_settings(settings: PipelineSettings, **overrides: Any) -> PipelineS
|
||||
if overrides.get("device") is not None:
|
||||
seg_updates["device"] = overrides["device"]
|
||||
|
||||
screen_color = (
|
||||
overrides["screen_color"]
|
||||
if overrides.get("screen_color") is not None
|
||||
else settings.screen_color
|
||||
)
|
||||
return PipelineSettings(
|
||||
chroma=chroma,
|
||||
trimap=_update_dataclass(trimap, trimap_updates),
|
||||
alpha_post=alpha_post,
|
||||
foreground=foreground,
|
||||
despill=_update_dataclass(despill, despill_updates),
|
||||
recolor=recolor,
|
||||
model=_update_dataclass(model, model_updates),
|
||||
segmentation=_update_dataclass(segmentation, seg_updates),
|
||||
screen_color=screen_color,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user