fix: constrain product lock scale adjust to source patch

This commit is contained in:
134 2026-07-06 01:30:01 +08:00
parent 26aa4fb12f
commit f6faf6bb44

View File

@ -2404,34 +2404,6 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
width: cutoutWidth,
});
if (!highConfidenceCutoutBbox) return null;
const refinedCutoutRaw = await applyScaleAdjustAlphaMaskToRgba({
alphaMask: highConfidenceCutoutMask,
height: cutoutHeight,
rawRgba: cleanedRaw,
width: cutoutWidth,
});
const cleanedCutout = await sharp(refinedCutoutRaw, {
raw: { channels: 4, height: cutoutHeight, width: cutoutWidth },
})
.png({ compressionLevel: 6 })
.toBuffer();
const alphaBbox = getScaleAdjustAlphaBoundingBox({
height: cutoutHeight,
rawRgba: refinedCutoutRaw,
width: cutoutWidth,
});
if (!alphaBbox) return null;
const alphaRatio = alphaBbox.count / Math.max(1, cutoutWidth * cutoutHeight);
const bboxCoversCanvas =
alphaBbox.width >= cutoutWidth * 0.97 &&
alphaBbox.height >= cutoutHeight * 0.97;
if (
alphaRatio < SCALE_ADJUST_RMBG_MIN_ALPHA_RATIO ||
(alphaRatio > SCALE_ADJUST_RMBG_MAX_SOLID_ALPHA_RATIO && bboxCoversCanvas)
) {
return null;
}
const fullAlphaMask = Buffer.from(highConfidenceCutoutMask);
const sourceMaskBuffer = sameSizeCutout
@ -2464,15 +2436,68 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
maskBuffer: sourceMaskBuffer,
threshold: 96,
});
const protectedPersonMask =
protectedPersonSide && sameSizeCutout && sourceCropRaw
? validateScaleAdjustProtectedPersonMask({
box: { width: cutoutWidth, height: cutoutHeight },
mask: buildScaleAdjustProtectedPersonSeedMask({
box: { left: 0, top: 0, width: cutoutWidth, height: cutoutHeight },
raw: sourceCropRaw,
side: protectedPersonSide,
width: cutoutWidth,
}),
})
: null;
const filteredSourceMask = filterScaleAdjustStructureComponents({
box: placement.sourceBox,
mask: highConfidenceSourceMask,
protectedPersonMask,
protectedPersonSide,
});
const filteredSourceBbox = getScaleAdjustMaskBoundingBox({
height: placement.sourceBox.height,
mask: filteredSourceMask,
width: placement.sourceBox.width,
});
const overlayAlphaMask =
sameSizeCutout && filteredSourceBbox
? filteredSourceMask
: highConfidenceCutoutMask;
const overlayAlphaBbox = getScaleAdjustMaskBoundingBox({
height: cutoutHeight,
mask: overlayAlphaMask,
width: cutoutWidth,
});
if (!overlayAlphaBbox) return null;
const refinedCutoutRaw = await applyScaleAdjustAlphaMaskToRgba({
alphaMask: overlayAlphaMask,
height: cutoutHeight,
rawRgba: cleanedRaw,
width: cutoutWidth,
});
const cleanedCutout = await sharp(refinedCutoutRaw, {
raw: { channels: 4, height: cutoutHeight, width: cutoutWidth },
})
.png({ compressionLevel: 6 })
.toBuffer();
const alphaBbox = getScaleAdjustAlphaBoundingBox({
height: cutoutHeight,
rawRgba: refinedCutoutRaw,
width: cutoutWidth,
});
if (!alphaBbox) return null;
const alphaRatio =
overlayAlphaBbox.count / Math.max(1, cutoutWidth * cutoutHeight);
const bboxCoversCanvas =
overlayAlphaBbox.width >= cutoutWidth * 0.97 &&
overlayAlphaBbox.height >= cutoutHeight * 0.97;
if (
alphaRatio < SCALE_ADJUST_RMBG_MIN_ALPHA_RATIO ||
(alphaRatio > SCALE_ADJUST_RMBG_MAX_SOLID_ALPHA_RATIO && bboxCoversCanvas)
) {
return null;
}
const sourceWashBaseMask = filteredSourceBbox
? solidifyScaleAdjustStructureMask({
box: placement.sourceBox,
@ -2582,9 +2607,13 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
alphaRatio: Number(alphaRatio.toFixed(3)),
cutoutHeight,
cutoutWidth,
filteredAlphaRatio: Number(
(overlayAlphaBbox.count / Math.max(1, cutoutWidth * cutoutHeight)).toFixed(3)
),
placedHeight,
placedWidth,
protectedPersonSide,
protectedPersonMaskApplied: Boolean(protectedPersonMask),
sameSizeCutout,
alphaBandingStats,
sourceHeight: placement.sourceBox.height,
@ -5229,7 +5258,7 @@ export async function POST(request: NextRequest) {
scaleAdjustPromptStrategy: isScaleAdjustOperation
? scaleAdjustPatchReference
? useScaleAdjustProductLockComposite
? "product-lock-background-plate-rmbg-v1-one-shot"
? "product-lock-background-plate-rmbg-v2-source-patch-one-shot"
: useScaleAdjustFullFrameStructurePatch
? "full-frame-source-locked-target-guide-v8-one-shot"
: scaleAdjustPatchReference.structureLockedDraft
@ -5251,7 +5280,8 @@ export async function POST(request: NextRequest) {
: undefined,
scaleAdjustPostCompositeApplied:
Boolean(scaleAdjustPatchReference) &&
!useScaleAdjustFullFrameStructurePatch,
(!useScaleAdjustFullFrameStructurePatch ||
useScaleAdjustProductLockComposite),
scaleAdjustUsesFullFrameOutput:
isScaleAdjustOperation &&
(!scaleAdjustPatchReference || useScaleAdjustFullFrameStructurePatch),
@ -5291,7 +5321,27 @@ export async function POST(request: NextRequest) {
? { maskImageUrl: scaleAdjustEditMaskUpload.url }
: undefined,
referenceImages,
scaleAdjustPatchComposite: scaleAdjustPatchReference && !useScaleAdjustFullFrameStructurePatch
scaleAdjustPatchComposite: useScaleAdjustProductLockComposite
? {
diffAlphaCutoff: 18,
diffAlphaMultiplier: 2.6,
diffCompareBlurPx: 1.1,
diffHighThreshold: 64,
diffLowThreshold: 20,
featherMaxPx: 34,
featherMinPx: 8,
featherRatio: 0.015,
generatedFrame: "full",
maskMode: "diff",
regions: scaleAdjustPatchCompositeRegions,
sourceImageUrl,
clipMaskImageUrl:
scaleAdjustPatchReference?.compositeClipMaskUrl || undefined,
workspaceRegion:
(scaleAdjustPatchReference as ScaleAdjustPatchReference)
.workspaceRect,
}
: scaleAdjustPatchReference && !useScaleAdjustFullFrameStructurePatch
? {
diffAlphaCutoff:
scaleAdjustPatchReference.structureLockedDraft ? 24 : 8,