Remove dead colour-model/despill code; simplify despill; refresh stale docs
- chroma: drop BackgroundModel.hsv_center/hue_sigma (unused since the green gating went away), their estimation, _hue_distance, and the now-unused hsv channel from convert_color_spaces (one fewer cvtColor per image). - despill: delete the dead green-channel-algebra path (the pipeline always passes a colour) and fold the remaining Lab-direction despill into a single despill() with no screen_color arg (127 -> 60 lines). Renamed despill_green -> despill. - settings: remove the now-dead ChromaSettings.hue_sigma_min and DespillSettings.green_excess_margin (plus the matching config lines). - docs/comments: generalise stale "green" wording to "background colour" (module docstring, alpha_post/trimap/foreground/settings) and rename the trimap variable green_bg -> screen_bg. Kept: the unmix foreground fallback, --matting-method chroma, and green/blue as illustrative examples. Verified: package compiles, both configs parse, and an auto-detect end-to-end run is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+7
-24
@@ -12,8 +12,6 @@ from .settings import ChromaSettings
|
||||
class BackgroundModel:
|
||||
rgb_center: tuple[float, float, float]
|
||||
rgb_sigma: tuple[float, float, float]
|
||||
hsv_center: tuple[float, float, float]
|
||||
hue_sigma: float
|
||||
lab_center: tuple[float, float, float]
|
||||
lab_sigma: float
|
||||
sample_count: int
|
||||
@@ -22,11 +20,6 @@ class BackgroundModel:
|
||||
return asdict(self)
|
||||
|
||||
|
||||
def _hue_distance(hue: np.ndarray, center: float) -> np.ndarray:
|
||||
diff = np.abs(hue.astype(np.float32) - float(center))
|
||||
return np.minimum(diff, 180.0 - diff)
|
||||
|
||||
|
||||
def _border_mask(height: int, width: int, ratio: float) -> np.ndarray:
|
||||
border = max(8, int(round(max(height, width) * ratio)))
|
||||
border = min(border, height // 2, width // 2)
|
||||
@@ -38,13 +31,12 @@ def _border_mask(height: int, width: int, ratio: float) -> np.ndarray:
|
||||
return mask
|
||||
|
||||
|
||||
def convert_color_spaces(rgb: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
||||
def convert_color_spaces(rgb: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
||||
"""Return ``(rgb_f, lab)``: RGB normalised to 0..1 and Lab (L 0..100, a/b signed)."""
|
||||
cv2 = require_cv2()
|
||||
rgb_f = rgb.astype(np.float32) / 255.0
|
||||
hsv = cv2.cvtColor(rgb, cv2.COLOR_RGB2HSV).astype(np.float32)
|
||||
hsv[..., 1:] /= 255.0
|
||||
lab = cv2.cvtColor(rgb_f, cv2.COLOR_RGB2LAB).astype(np.float32)
|
||||
return rgb_f, hsv, lab
|
||||
return rgb_f, lab
|
||||
|
||||
|
||||
def parse_hex_color(text: str) -> tuple[float, float, float]:
|
||||
@@ -116,7 +108,7 @@ def detect_background_color(
|
||||
Pure: reads pixels only, with no matting side effects.
|
||||
"""
|
||||
settings = settings or ChromaSettings()
|
||||
rgb_f, _, lab = convert_color_spaces(rgb)
|
||||
rgb_f, lab = convert_color_spaces(rgb)
|
||||
mask, _, _ = _background_border_cluster(lab, settings)
|
||||
return tuple(float(x) for x in np.median(rgb_f[mask], axis=0))
|
||||
|
||||
@@ -126,7 +118,7 @@ def estimate_background_model(
|
||||
settings: ChromaSettings,
|
||||
screen_color: tuple[float, float, float] | None = None,
|
||||
) -> tuple[BackgroundModel, tuple[np.ndarray, np.ndarray, np.ndarray]]:
|
||||
rgb_f, hsv, lab = convert_color_spaces(rgb)
|
||||
rgb_f, lab = convert_color_spaces(rgb)
|
||||
if screen_color is None:
|
||||
# AUTO: sample the flat colour that dominates the border (raises if there is
|
||||
# no clean flat background). Its own pixels are the model -- no seed search.
|
||||
@@ -146,7 +138,6 @@ def estimate_background_model(
|
||||
sample_mask = dist <= np.percentile(dist, 10.0)
|
||||
|
||||
rgb_samples = rgb_f[sample_mask]
|
||||
hsv_samples = hsv[sample_mask]
|
||||
lab_samples = lab[sample_mask]
|
||||
|
||||
rgb_center = np.median(rgb_samples, axis=0)
|
||||
@@ -154,12 +145,6 @@ def estimate_background_model(
|
||||
np.percentile(np.abs(rgb_samples - rgb_center), 75, axis=0) * 1.4826,
|
||||
settings.rgb_sigma_min,
|
||||
)
|
||||
hsv_center = np.median(hsv_samples, axis=0)
|
||||
hue_center = float(hsv_center[0])
|
||||
hue_dists = _hue_distance(hsv_samples[:, 0], hue_center)
|
||||
hue_sigma = max(
|
||||
float(np.percentile(hue_dists, 75) * 1.4826), settings.hue_sigma_min
|
||||
)
|
||||
lab_center = np.median(lab_samples, axis=0)
|
||||
lab_dists = np.linalg.norm(lab_samples - lab_center, axis=1)
|
||||
lab_sigma = max(
|
||||
@@ -169,13 +154,11 @@ def estimate_background_model(
|
||||
model = BackgroundModel(
|
||||
rgb_center=tuple(float(x) for x in rgb_center),
|
||||
rgb_sigma=tuple(float(x) for x in rgb_sigma),
|
||||
hsv_center=tuple(float(x) for x in hsv_center),
|
||||
hue_sigma=float(hue_sigma),
|
||||
lab_center=tuple(float(x) for x in lab_center),
|
||||
lab_sigma=float(lab_sigma),
|
||||
sample_count=int(sample_mask.sum()),
|
||||
)
|
||||
return model, (rgb_f, hsv, lab)
|
||||
return model, (rgb_f, lab)
|
||||
|
||||
|
||||
def compute_bg_confidence(
|
||||
@@ -189,7 +172,7 @@ def compute_bg_confidence(
|
||||
model, spaces = estimate_background_model(rgb, settings, screen_color)
|
||||
else:
|
||||
spaces = convert_color_spaces(rgb)
|
||||
rgb_f, hsv, lab = spaces
|
||||
rgb_f, lab = spaces
|
||||
|
||||
lab_center = np.asarray(model.lab_center, dtype=np.float32)
|
||||
lab_dist = np.linalg.norm(lab - lab_center, axis=2)
|
||||
|
||||
Reference in New Issue
Block a user