align grid split with reference workflow
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-27 11:27:53 +08:00
parent 40af82a807
commit 9ad5d69bec
2 changed files with 15 additions and 23 deletions

View File

@ -1173,7 +1173,7 @@ function createNineGridCompositeNode({
nineGridCells: Array.from({ length: cellCount }).map((_, index) => getGridCellVisual(index)),
nineGridComposite: true,
nodeType: "image",
outputSizeLabel: cellCount === 9 ? "2752 × 1536" : "",
outputSizeLabel: "2752 × 1536",
params: {
columns,
functionKey,
@ -1810,7 +1810,7 @@ function normalizeGridSplitState(value: unknown): GridSplitState | null {
rects,
rows,
selectedIndices,
sourceMode: String(record.sourceMode || "detected-lines"),
sourceMode: String(record.sourceMode || "uniform-grid"),
};
}
@ -1875,7 +1875,9 @@ function getLineScore(data: Uint8ClampedArray, width: number, height: number, ax
const alpha = data[offset + 3] / 255;
if (alpha < 0.1) continue;
const luminance = data[offset] * 0.299 + data[offset + 1] * 0.587 + data[offset + 2] * 0.114;
score += luminance < 96 ? ((96 - luminance) / 96) * alpha : 0;
const darkScore = luminance < 96 ? ((96 - luminance) / 96) * alpha : 0;
const lightScore = luminance > 220 ? ((luminance - 220) / 35) * alpha : 0;
score += Math.max(darkScore, lightScore);
samples += 1;
}
@ -3289,9 +3291,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
if (action === "crop") {
const { columns, rows, tileCount } = normalizeGridOption(option);
const anchorMediaUrl = getNodeMediaUrl(anchor);
const currentSplit = getNodeGridSplitState(anchor);
const isSyntheticGrid = Boolean(anchor.draftValues?.nineGridComposite) && !anchorMediaUrl;
if (currentSplit && currentSplit.columns === columns && currentSplit.rows === rows) {
setNodes((current) =>
current.map((node) =>
@ -3311,14 +3311,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
toast.success("已取消宫格切分");
return;
}
const detectedSplit =
!isSyntheticGrid && anchorMediaUrl
? await detectGridSplitFromImage(anchorMediaUrl, rows, columns)
: null;
const rects =
detectedSplit?.rects && detectedSplit.rects.length >= tileCount
? detectedSplit.rects
: createEqualGridRects(rows, columns);
const rects = createEqualGridRects(rows, columns);
setNodes((current) =>
current.map((node) =>
node.id === anchor.id
@ -3328,11 +3321,11 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
...(node.draftValues || {}),
gridSplit: {
columns,
detectedDivider: Boolean(detectedSplit?.detected),
detectedDivider: false,
rects,
rows,
selectedIndices: [],
sourceMode: isSyntheticGrid ? "synthetic-grid" : "detected-lines",
sourceMode: "uniform-grid",
},
},
}
@ -3344,11 +3337,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
setNodeContextMenu(null);
setConnectionMenu(null);
setActivePanel(null);
toast.success(
detectedSplit?.detected
? `已在当前图上识别黑色分割线,进入 ${tileCount} 宫格选择模式`
: `已在当前图上按 ${columns}x${rows} 进入宫格选择模式`
);
toast.success(`已在当前图上按 ${columns}x${rows} 进入 ${tileCount} 宫格选择模式`);
return;
}

View File

@ -84,7 +84,7 @@ const defaultFunctions: VideoCanvasFunctionDefinition[] = [
enabled: true,
creditCost: 14,
prompt:
"以选中图片作为角色、服装、发型、场景光线和电影质感的唯一参考,生成一张 5x5 连贯分镜合成图。必须是 25 个连续镜头,体现从远景建立场景、人物动作推进、情绪变化、细节特写到结尾反应的完整微型叙事,不是同一张图重复裁切。保持同一角色身份和绿色服装一致,森林自然光线统一;每格景别、机位、主体大小或动作都要有明显差异。输出为单张 16:9 图片,5x5 等分排版,使用清晰分割线,不能出现文字、水印、编号或多余边框说明。",
"以选中图片作为角色、服装、发型、场景光线和电影质感的唯一参考,生成一张 5x5 连贯分镜合成图。必须是 25 个连续镜头,体现从远景建立场景、人物动作推进、情绪变化、细节特写到结尾反应的完整微型叙事,不是同一张图重复裁切。保持同一角色身份和绿色服装一致,森林自然光线统一;每格景别、机位、主体大小或动作都要有明显差异。输出为单张 16:9 图片,必须严格 5x5 等分排版,25 个宫格的宽高一致、间距一致、边界完整,所有宫格之间使用清晰纯黑分割线,分割线等宽且横线竖线都要贯穿整张图;禁止使用白线、浅色线、柔边、渐变线、不规则拼贴、错位排版、跨格大图、留白边距、文字、水印、编号或额外边框说明。",
description: "官方 25 宫格连贯分镜:生成 5x5 连续镜头合成图。",
},
{
@ -127,8 +127,8 @@ const defaultFunctions: VideoCanvasFunctionDefinition[] = [
route: "local",
enabled: true,
creditCost: 0,
prompt: "识别黑色宫格分割线,将合成图切分为可单独调整的镜头图片。",
description: "浏览器端识别黑色分割线并生成切片节点;后端可后续替换为更稳的图像分割服务。",
prompt: "按当前图的标准宫格布局进行固定等分切分,将合成图切分为可单独调整的镜头图片。",
description: "对齐官方画布:4/9/16/25 和自定义宫格都按当前图的行列固定等分切分,并支持在当前图上多选宫格后继续创建生图或高清节点。",
},
{
key: "lighting",
@ -313,6 +313,9 @@ const legacyFunctionPrompts: Record<string, string[]> = {
"以选中图片作为角色身份、服装、发型、场景光线、镜头距离和画面质感的唯一参考,生成一张 2x2 剧情推演四宫格合成图。四格都必须保持参考图的近景/半身近中景人物构图,主体占画面主要面积,不要远景、全景、森林空镜或主体很小的画面。四格是同一角色在同一自然光场景中的连续轻微剧情变化:1 正面安静凝视,2 保留参考图抬手/袖摆动作的延续,3 视线或表情轻微变化,4 情绪收束的近中景反应。保持五官、发型、绿色服装、柔和森林逆光、色调和景深一致;每格角度和动作有轻微差异,但不能像 9 个不同机位分镜。输出单张 16:9 图片,2x2 等分排版,分割线清晰干净,不能出现文字、水印、编号、边框标签或 3x3/5x5 宫格。",
"以选中图片作为角色、服装、发型、场景光线的唯一参考,生成一张 3x3 多机位分镜合成图。必须是 9 个明显不同的镜头画面,不是同一张图裁切或重复人脸。九格分别包含:1 森林环境远景/主体很小,2 全身远景,3 中景正面,4 侧面半身,5 低机位或俯拍,6 面部近景,7 手部/衣袖/动作细节,8 背面或侧背,9 仰视或情绪特写。保持同一角色身份、绿色服装、自然森林光线一致,每格构图、景别、机位和主体大小必须不同。输出为单张 16:9 图片,九格之间使用清晰黑色分割线,不能出现文字、水印、编号,不能白底棚拍。",
],
"continuous-storyboard-grid-25": [
"以选中图片作为角色、服装、发型、场景光线和电影质感的唯一参考,生成一张 5x5 连贯分镜合成图。必须是 25 个连续镜头,体现从远景建立场景、人物动作推进、情绪变化、细节特写到结尾反应的完整微型叙事,不是同一张图重复裁切。保持同一角色身份和绿色服装一致,森林自然光线统一;每格景别、机位、主体大小或动作都要有明显差异。输出为单张 16:9 图片,5x5 等分排版,使用清晰分割线,不能出现文字、水印、编号或多余边框说明。",
],
"character-three-view": [
"以输入角色图为唯一角色参考,生成正面、侧面、背面三视图角色设定图。保持五官、发型、服装、颜色和体型一致,干净白底,三视图水平排布,适合后续视频角色一致性使用。",
],