fix: keep product out of scale repair crop prompt
This commit is contained in:
parent
2cb6f51a63
commit
d69346de42
@ -124,6 +124,7 @@ type ScaleAdjustCropReference = {
|
||||
url: string;
|
||||
};
|
||||
type ScaleAdjustPatchReference = {
|
||||
backgroundPlateCropUrl?: string | null;
|
||||
backgroundPlateFullUrl?: string | null;
|
||||
compositeClipMaskUrl?: string | null;
|
||||
repairBlendMaskUrl?: string | null;
|
||||
@ -4024,6 +4025,7 @@ async function createScaleAdjustPatchReference(params: {
|
||||
]);
|
||||
|
||||
return {
|
||||
backgroundPlateCropUrl: null,
|
||||
backgroundPlateFullUrl: backgroundPlateFullUpload?.url || null,
|
||||
compositeClipMaskUrl: compositeClipMaskUpload?.url || null,
|
||||
repairBlendMaskUrl: repairBlendMaskUpload?.url || null,
|
||||
@ -4051,6 +4053,12 @@ async function createScaleAdjustPatchReference(params: {
|
||||
.png({ compressionLevel: 6 })
|
||||
.toBuffer(),
|
||||
]);
|
||||
const backgroundPlateCropBuffer = targetDraftReference.backgroundPlateBuffer
|
||||
? await sharp(targetDraftReference.backgroundPlateBuffer, { failOn: "none" })
|
||||
.extract(workspacePixelRect)
|
||||
.png({ compressionLevel: 6 })
|
||||
.toBuffer()
|
||||
: null;
|
||||
const [sourceCropUpload, targetDraftUpload, targetDraftFullUpload] =
|
||||
await Promise.all([
|
||||
uploadScaleAdjustPrepAsset(
|
||||
@ -4068,6 +4076,7 @@ async function createScaleAdjustPatchReference(params: {
|
||||
]);
|
||||
const [
|
||||
backgroundPlateFullUpload,
|
||||
backgroundPlateCropUpload,
|
||||
productLockOverlayUpload,
|
||||
productLockProtectMaskUpload,
|
||||
compositeClipMaskUpload,
|
||||
@ -4079,6 +4088,10 @@ async function createScaleAdjustPatchReference(params: {
|
||||
`canvas-scale-adjust-background-plate-${suffix}.jpg`,
|
||||
backgroundPlateUploadBuffer
|
||||
),
|
||||
uploadOptionalScaleAdjustAsset(
|
||||
`canvas-scale-adjust-background-plate-crop-${suffix}.png`,
|
||||
backgroundPlateCropBuffer
|
||||
),
|
||||
uploadOptionalScaleAdjustAsset(
|
||||
`canvas-scale-adjust-product-lock-overlay-${suffix}.png`,
|
||||
targetDraftReference.productLockOverlayBuffer
|
||||
@ -4112,6 +4125,7 @@ async function createScaleAdjustPatchReference(params: {
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundPlateCropUrl: backgroundPlateCropUpload?.url || null,
|
||||
backgroundPlateFullUrl: backgroundPlateFullUpload?.url || null,
|
||||
compositeClipMaskUrl: compositeClipMaskUpload?.url || null,
|
||||
repairBlendMaskUrl: repairBlendMaskUpload?.url || null,
|
||||
@ -5148,6 +5162,54 @@ function buildScaleAdjustProductLockBackgroundPrompt(
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
function buildScaleAdjustProductLockBackgroundCropPrompt(
|
||||
regions: NormalizedLocalEditRegion[],
|
||||
scalePercent: ScaleAdjustPercent | null | undefined,
|
||||
patchReference: ScaleAdjustPatchReference,
|
||||
sourceSize: { width: number; height: number }
|
||||
) {
|
||||
const workspace = patchReference.workspacePixelRect;
|
||||
const regionLines = regions
|
||||
.map((region) => {
|
||||
const targetRect = getScaleAdjustTargetRect(region, scalePercent);
|
||||
const targetPixelRect =
|
||||
region.targetPixelRect ||
|
||||
rectToPixels(targetRect, sourceSize.width, sourceSize.height);
|
||||
const sourceInCrop = {
|
||||
left: Math.max(0, region.pixelRect.left - workspace.left),
|
||||
top: Math.max(0, region.pixelRect.top - workspace.top),
|
||||
width: region.pixelRect.width,
|
||||
height: region.pixelRect.height,
|
||||
};
|
||||
const targetInCrop = {
|
||||
left: Math.max(0, targetPixelRect.left - workspace.left),
|
||||
top: Math.max(0, targetPixelRect.top - workspace.top),
|
||||
width: targetPixelRect.width,
|
||||
height: targetPixelRect.height,
|
||||
};
|
||||
return `Region ${region.index}: in this crop, erase the old selected furniture/product footprint around x=${sourceInCrop.left}, y=${sourceInCrop.top}, w=${sourceInCrop.width}, h=${sourceInCrop.height}. Keep the future target footprint x=${targetInCrop.left}, y=${targetInCrop.top}, w=${targetInCrop.width}, h=${targetInCrop.height} empty and clean; the locked product pixels will be composited there after generation. User request: ${region.prompt}.`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return [
|
||||
"Cropped background repair for product-locked scale adjustment.",
|
||||
`Return exactly one clean realistic crop with the same framing, aspect ratio, and pixel extent as input image 1. This crop maps to full-photo pixels left=${workspace.left}, top=${workspace.top}, width=${workspace.width}, height=${workspace.height}.`,
|
||||
"Input image 1 is the original crop from the source photo. Input image 2 is a rough empty-background repair guide crop where the selected furniture/product footprint has been wiped.",
|
||||
"Important: do not draw, recreate, move, scale, duplicate, or redesign the selected furniture/product in your output. The system will composite the locked original product pixels into the target footprint after your crop is returned.",
|
||||
"Your only job is to repair the old footprint into natural wall, curtain, floor, rug, shadow, sofa edge, and background, while keeping non-target people and non-target objects stable.",
|
||||
"If input image 2 contains haze, gray wash, ghost silhouettes, crop edges, black holes, rough mask shapes, or pasted fragments, treat them as repair hints only. Do not preserve them as visible content.",
|
||||
"Preserve any non-target person exactly: do not change face, body, hands, legs, clothes, pose, hair, or book. Do not cover the person with furniture.",
|
||||
"Keep the target footprint empty and natural; do not place the selected furniture/product there.",
|
||||
"Do not output boxes, masks, labels, coordinate marks, UI marks, arrows, guide overlays, text, seams, rectangular patch edges, haze blocks, ghost copies, or old-size remnants.",
|
||||
"中文硬约束:这是产品结构锁定的局部背景修补。你只输出干净背景裁切,不要生成目标家具/商品;旧位置的目标家具/商品必须擦除并补成自然墙面、窗帘、地面、阴影和背景。目标家具/商品会在你输出后由系统用原图锁定像素叠回。最终不能有旧尺寸残影、矩形雾块、贴片边、黑洞、标注框,也不能改变人物。",
|
||||
"",
|
||||
"Region instructions:",
|
||||
regionLines,
|
||||
"",
|
||||
"Success check before returning: the selected furniture/product is absent from the crop, the old footprint is naturally repaired, the future target footprint is clean, and the crop looks like one natural photograph.",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const session = await auth();
|
||||
@ -5506,6 +5568,10 @@ export async function POST(request: NextRequest) {
|
||||
const useScaleAdjustProductLockMaskEdit =
|
||||
useScaleAdjustProductLockComposite &&
|
||||
canUseScaleAdjustProductLockMaskEdit;
|
||||
const useScaleAdjustProductLockCropBackground =
|
||||
useScaleAdjustProductLockComposite &&
|
||||
!useScaleAdjustFullFrameStructurePatch &&
|
||||
Boolean(scaleAdjustPatchReference?.backgroundPlateCropUrl);
|
||||
const useScaleAdjustPatchTargetDraftPrimary = Boolean(scaleAdjustPatchReference);
|
||||
const includeScaleAdjustPatchSourceReference =
|
||||
Boolean(scaleAdjustPatchReference);
|
||||
@ -5531,6 +5597,13 @@ export async function POST(request: NextRequest) {
|
||||
scalePercent,
|
||||
{ width: sourceWidth, height: sourceHeight }
|
||||
)
|
||||
: useScaleAdjustProductLockCropBackground
|
||||
? buildScaleAdjustProductLockBackgroundCropPrompt(
|
||||
regions,
|
||||
scalePercent,
|
||||
scaleAdjustPatchReference,
|
||||
{ width: sourceWidth, height: sourceHeight }
|
||||
)
|
||||
: buildScaleAdjustPatchPrompt(
|
||||
regions,
|
||||
scalePercent,
|
||||
@ -5613,6 +5686,13 @@ export async function POST(request: NextRequest) {
|
||||
...scaleAdjustCropReferenceImageUrls,
|
||||
...manualRegionReferenceImageUrls,
|
||||
]
|
||||
: useScaleAdjustProductLockCropBackground
|
||||
? [
|
||||
scaleAdjustPatchReference.sourceCropUrl,
|
||||
scaleAdjustPatchReference.backgroundPlateCropUrl as string,
|
||||
...scaleAdjustCropReferenceImageUrls,
|
||||
...manualRegionReferenceImageUrls,
|
||||
]
|
||||
: useScaleAdjustPatchTargetDraftPrimary
|
||||
? [
|
||||
scaleAdjustPatchReference.targetDraftUrl,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user