Apply Colored Mark color to mask previews

This commit is contained in:
alisson-anjos
2026-10-13 17:06:14 +00:00
parent 507d5bc60a
commit dca37ddc0f
3 changed files with 21 additions and 6 deletions
+13 -4
View File
@@ -1390,19 +1390,25 @@ def uncrop(result: torch.Tensor, shot: dict, edge_hardness: float = 0.0, match_c
return out
def mask_preview(path: str, analysis: dict, start: int, length: int, spec: dict, count: int = 6) -> dict:
"""A few frames of the shot with the mask in red and the crop box, as data URLs."""
def mask_preview(path: str, analysis: dict, start: int, length: int, spec: dict, count: int = 6,
color: str = "#ff283c", opacity: float = 0.55) -> dict:
"""A few frames of the shot with the selected region tinted and the crop box, as data URLs."""
import cv2
r = shot_mask(path, analysis, start, length, spec)
masks, (w, h), box = r["masks"], r["size"], r["box"]
src = _timeline(analysis["n_src"], analysis["fps_src"], float(analysis["fps"]))
picks = sorted(set(int(round(i)) for i in np.linspace(0, length - 1, min(count, length))))
frames = _read_frames(path, src[np.clip(np.array(picks) + start, 0, analysis["n"] - 1)], (w, h))
try:
tint = np.array([int(color[i:i + 2], 16) for i in (1, 3, 5)], dtype=np.float32)
alpha = min(0.8, max(0.05, float(opacity)))
except (TypeError, ValueError, IndexError):
tint, alpha = np.array([255, 40, 60], dtype=np.float32), 0.55
out = []
for i, fr in zip(picks, frames):
img = fr.copy()
m = masks[min(i, masks.shape[0] - 1)].numpy().astype(bool)
img[m] = (img[m] * 0.45 + np.array([255, 40, 60]) * 0.55).astype(np.uint8)
img[m] = (img[m].astype(np.float32) * (1 - alpha) + tint * alpha).astype(np.uint8)
if box:
x0, y0, x1, y1 = box_px(box, w, h)
cv2.rectangle(img, (x0, y0), (x1 - 1, y1 - 1), (255, 210, 90), 2)
@@ -4023,7 +4029,10 @@ try:
import asyncio # SAM 3 takes seconds: keep the server responsive
_outside_prompt()
out = await asyncio.get_running_loop().run_in_executor(
None, lambda: mask_preview(path, a, seg["start"], seg["end"] - seg["start"], spec, int(body.get("count", 6))))
None, lambda: mask_preview(path, a, seg["start"], seg["end"] - seg["start"], spec,
int(body.get("count", 6)),
seg.get("color_guide_color") if seg.get("color_guide") else "#ff283c",
seg.get("color_guide_opacity") if seg.get("color_guide") else 0.55))
except Exception as exc: # noqa: BLE001
return web.json_response({"error": f"{type(exc).__name__}: {exc}"}, status=500)
return web.json_response(out)
+4 -1
View File
@@ -23,7 +23,10 @@ export function pointsModal(c) {
h("div", { class: "mbox" }, [
h("div", { class: "row", style: "margin-bottom:6px" }, [h("span", { class: "sect" }, `Shot #${modal.idx + 1} · points`),
ms.color_guide ? h("label", { class: "row", style: "gap:6px;align-items:center" }, [h("span", { class: "hint" }, "Colored Mark"),
h("select", { value: ms.color_guide_color || plan.global_color_guide_ref1 || "#00ff00", style: "width:auto", onChange: e => setMeta(modal.idx, "color_guide_color", e.target.value) },
h("select", { value: ms.color_guide_color || plan.global_color_guide_ref1 || "#00ff00", style: "width:auto", onChange: e => {
setMeta(modal.idx, "color_guide_color", e.target.value);
if (modal.prev) c.previewMask(modal.idx, { points: modal.points, key: modal.key, text: modal.text }, true);
} },
[["#00ff00", "Green"], ["#9b30ff", "Purple"], ["#ff2020", "Red"], ["#168cff", "Blue"], ["#ffe600", "Yellow"], ["#ff00d4", "Magenta"], ["#00e5c0", "Cyan"]].map(([v, n]) => h("option", { value: v }, n)))]) : null,
hint("click = keep (green) · right-click or shift+click = exclude (red) · click a point to remove it")]),
h("div", { class: "mimg", onContextmenu: e => e.preventDefault(), onPointerdown: e => {
+4 -1
View File
@@ -135,7 +135,10 @@ function editor(c, cur) {
check(!!cur.color_guide, v => c.setMeta(i, "color_guide", v), "🎨 Colored Mark",
"Color the selected region in the source video as a translucent visual marker. It does not create or enable an inpainting mask."),
h("label", { class: "row", style: "gap:6px;align-items:center" }, [h("span", { class: "hint" }, "Region color · Ref 1"),
h("select", { value: cur.color_guide_color || plan.global_color_guide_ref1 || "#00ff00", style: "width:auto", onChange: e => c.setMeta(i, "color_guide_color", e.target.value) },
h("select", { value: cur.color_guide_color || plan.global_color_guide_ref1 || "#00ff00", style: "width:auto", onChange: e => {
c.setMeta(i, "color_guide_color", e.target.value);
if (maskPrev.value[segKey(cur)]) c.previewMask(i);
} },
GUIDE_COLORS.map(([v, label]) => h("option", { value: v }, label)))]),
]),
cur.color_guide ? h("details", { class: "note", style: "margin:4px 0;padding:6px 8px", open: !!cur.color_guide_text2 }, [