auto-save 2026-05-14 06:27 (~4)

This commit is contained in:
2026-05-14 06:28:04 +08:00
parent 2d36adafd3
commit 6480d69c63
4 changed files with 50 additions and 35 deletions

View File

@@ -1,19 +1,5 @@
{
"entries": [
{
"files_changed": 2,
"hash": "e6b8615",
"message": "auto-save 2026-05-12 17:23 (~2)",
"ts": "2026-05-12T17:23:21+08:00",
"type": "commit"
},
{
"files_changed": 6,
"hash": "6a9abea",
"message": "auto-save 2026-05-12 17:28 (~6)",
"ts": "2026-05-12T17:28:54+08:00",
"type": "commit"
},
{
"files_changed": 1,
"hash": "f3ec026",
@@ -3351,6 +3337,19 @@
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令codex · 2 项未提交变更 · 最近提交auto-save 2026-05-14 06:16 (~5)",
"files_changed": 2
},
{
"ts": "2026-05-14T06:22:32+08:00",
"type": "commit",
"message": "auto-save 2026-05-14 06:22 (~2)",
"hash": "2d36ada",
"files_changed": 2
},
{
"ts": "2026-05-13T22:23:14Z",
"type": "session-heartbeat",
"message": "Claude 会话活跃 · 最近命令claude · 1 项未提交变更 · 最近提交auto-save 2026-05-14 06:22 (~2)",
"files_changed": 1
}
]
}

View File

@@ -448,7 +448,7 @@ def run(cmd: list[str], cwd: Path | None = None) -> str:
# ---- 启发式选帧工具 ----
import imagehash
import numpy as np
from PIL import Image, ImageEnhance, ImageFilter, ImageOps
from PIL import Image, ImageChops, ImageEnhance, ImageFilter, ImageOps
def _sharpness_from_gray(g: np.ndarray) -> float:
@@ -592,6 +592,7 @@ def _normalize_asset_image(
size: AssetSize,
background: AssetBackground = "white",
square: bool = False,
fill_subject: bool = False,
) -> tuple[int, int]:
import io as _io
target_w, target_h = _asset_target_size(source_path, size, square=square)
@@ -599,7 +600,25 @@ def _normalize_asset_image(
out_path.parent.mkdir(parents=True, exist_ok=True)
with Image.open(_io.BytesIO(img_bytes)) as raw:
img = raw.convert("RGB")
img.thumbnail((target_w, target_h), Image.Resampling.LANCZOS)
if fill_subject:
diff = ImageChops.difference(img, Image.new("RGB", img.size, bg))
mask = diff.convert("L").point(lambda px: 255 if px > 18 else 0)
bbox = mask.getbbox()
if bbox:
left, top, right, bottom = bbox
pad_x = round((right - left) * 0.06)
pad_y = round((bottom - top) * 0.06)
img = img.crop((
max(0, left - pad_x),
max(0, top - pad_y),
min(img.width, right + pad_x),
min(img.height, bottom + pad_y),
))
max_w = max(1, round(target_w * 0.92))
max_h = max(1, round(target_h * 0.94))
img.thumbnail((max_w, max_h), Image.Resampling.LANCZOS)
else:
img.thumbnail((target_w, target_h), Image.Resampling.LANCZOS)
canvas = Image.new("RGB", (target_w, target_h), bg)
canvas.paste(img, ((target_w - img.width) // 2, (target_h - img.height) // 2))
canvas.save(out_path, "JPEG", quality=95)
@@ -699,6 +718,8 @@ SUBJECT_VIEW_LABELS: dict[str, str] = {
"back": "背面",
"left": "左侧",
"right": "右侧",
"three_quarter_left": "左前 45°",
"three_quarter_right": "右前 45°",
"side": "侧面",
"side_walk": "侧面走路",
"top": "顶部视角",
@@ -727,10 +748,10 @@ def _subject_view_labels(kind: SubjectKind, requested: list[str] | None = None)
return [
("front", "正面站立"),
("back", "背面站立"),
("side", "站立"),
("side_walk", "侧面走路"),
("expression_neutral", "中性表情"),
("expression_relaxed", "放松表情"),
("left", "侧站立"),
("right", "右侧站立"),
("three_quarter_left", "左前 45° 站立"),
("three_quarter_right", "右前 45° 站立"),
]
return [
("front", "正面"),

View File

@@ -36,15 +36,10 @@ const OBJECT_VIEW_OPTIONS = [
const LIVING_VIEW_OPTIONS = [
["front", "正面"],
["back", "背面"],
["side", "侧"],
["side_walk", "走路"],
["expression_happy", ""],
["expression_angry", ""],
["expression_sad", "哀"],
["expression_relaxed", "乐/放松"],
["action_sit", "坐"],
["action_hold", "手持"],
["action_use", "使用"],
["left", "侧"],
["right", "右侧"],
["three_quarter_left", "左前 45°"],
["three_quarter_right", "右前 45°"],
]
type LightboxTab = "clean" | "scene" | "subject" | "review"
@@ -266,7 +261,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
views,
})
onJobUpdate?.(updated)
toast.success(`统一主体资产包已生成 · ${views.length} 张 · ${subjectReferenceFrameIndices.length} 帧参考`)
toast.success(`统一主体重绘完成 · ${views.length} 张 · ${subjectReferenceFrameIndices.length} 帧参考`)
} catch (e) {
toast.error("主体资产包生成失败:" + (e instanceof Error ? e.message : String(e)))
} finally {
@@ -924,7 +919,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
<span className="text-[9.5px] text-white/35 font-normal ml-auto"> {subjectReferenceLabel}</span>
</div>
<div className="mb-2 rounded-md border border-white/10 bg-white/[0.035] px-2.5 py-1.5 text-[10.5px] leading-relaxed text-white/45">
</div>
{!hasUnifiedSubject && (
@@ -1053,7 +1048,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
<div className="mt-2 rounded-md border border-violet-300/15 bg-violet-500/[0.08] p-2">
<div className="mb-2 flex items-center justify-between gap-2">
<div className="text-[11px] font-semibold text-white/90"></div>
<div className="text-[11px] font-semibold text-white/90"></div>
<span className="text-[9.5px] font-mono text-white/35">
{subjectReferenceLabel}
</span>
@@ -1084,7 +1079,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
onClick={() => handleGenerateSubjectPackage(e.id, frameIndex)}
disabled={isSubjectGenerating || activeViews.length === 0}
className="rounded bg-violet-500/70 px-1.5 py-1 text-[10px] font-medium text-white transition hover:bg-violet-400 disabled:cursor-wait disabled:opacity-45 inline-flex items-center justify-center gap-1"
title="用多张关键帧参考生成同一个主体的多视角 / 动作 / 表情资产"
title="用多张关键帧参考重绘同一个主体的六张标准站立图"
>
{isSubjectGenerating ? <Loader2 className="h-3 w-3 animate-spin" /> : <Wand2 className="h-3 w-3" />}
{isSubjectGenerating ? "生成" : "生成"}
@@ -1150,7 +1145,7 @@ export function FrameLightbox({ jobId, frames, activeIndex, selected, onClose, o
)}
<div className="mt-1.5 text-[10px] text-white/35 leading-relaxed">
使
使
</div>
</section>
</div>

View File

@@ -1561,7 +1561,7 @@ export function VisualLabNode({ data, selected }: any) {
onClick={(e) => { e.stopPropagation(); openFirstFrame() }}
disabled={!job || frames.length === 0}
className="min-h-14 rounded-md border border-white/10 px-2 py-2 text-left transition hover:border-violet-300/50 hover:bg-violet-400/10 disabled:opacity-35"
title="用多张关键帧生成统一主体的多视角 / 动作 / 表情资产包"
title="用多张关键帧参考重绘统一主体的六张标准站立图"
>
<div className="mb-1 flex items-center gap-1 text-[var(--text-strong)] text-[12px] font-semibold">
<Package className="h-3 w-3 text-violet-300" />