fix: harden scale adjust person occlusion masks

This commit is contained in:
134 2026-07-06 03:00:28 +08:00
parent f7a5accb61
commit 6694846c58

View File

@ -1726,6 +1726,34 @@ function buildScaleAdjustProtectedPersonSeedMask(params: {
});
}
function buildScaleAdjustProtectedPersonGeometryMask(params: {
box: { width: number; height: number };
side: ScaleAdjustProtectedPersonSide | null;
}) {
const { box, side } = params;
if (!side) return null;
const mask = new Uint8Array(box.width * box.height);
for (let y = 0; y < box.height; y += 1) {
for (let x = 0; x < box.width; x += 1) {
const xr = x / Math.max(1, box.width);
const yr = y / Math.max(1, box.height);
const protect =
side === "right"
? (xr >= 0.72 && yr >= 0.26) ||
(xr >= 0.58 && yr >= 0.56) ||
(xr >= 0.48 && yr >= 0.7)
: side === "left"
? (xr <= 0.28 && yr >= 0.26) ||
(xr <= 0.42 && yr >= 0.56) ||
(xr <= 0.52 && yr >= 0.7)
: (yr >= 0.62 && (xr <= 0.2 || xr >= 0.8)) ||
(yr >= 0.72 && (xr <= 0.34 || xr >= 0.66));
if (protect) mask[y * box.width + x] = 255;
}
}
return mask;
}
function filterScaleAdjustStructureComponents(params: {
box: { width: number; height: number };
mask: Uint8Array;
@ -1821,13 +1849,15 @@ function filterScaleAdjustStructureComponents(params: {
if (protectedPersonSide === "right") {
return (
(pixelX >= width * 0.7 && pixelY >= height * 0.38) ||
(pixelX >= width * 0.62 && pixelY >= height * 0.56)
(pixelX >= width * 0.62 && pixelY >= height * 0.56) ||
(pixelX >= width * 0.48 && pixelY >= height * 0.7)
);
}
if (protectedPersonSide === "left") {
return (
(pixelX <= width * 0.3 && pixelY >= height * 0.38) ||
(pixelX <= width * 0.38 && pixelY >= height * 0.56)
(pixelX <= width * 0.38 && pixelY >= height * 0.56) ||
(pixelX <= width * 0.52 && pixelY >= height * 0.7)
);
}
if (protectedPersonSide === "auto") {
@ -2110,7 +2140,7 @@ async function buildScaleAdjustMaskWashPatch(params: {
rgba[offset] = Math.round(background.r);
rgba[offset + 1] = Math.round(background.g);
rgba[offset + 2] = Math.round(background.b);
rgba[offset + 3] = Math.round((alpha[index] || 0) * 0.9);
rgba[offset + 3] = Math.min(255, Math.round((alpha[index] || 0) * 0.985));
}
return sharp(rgba, {
raw: { channels: 4, height: box.height, width: box.width },
@ -2714,12 +2744,20 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
.toBuffer();
const targetClipMaskPatch =
await buildScaleAdjustOverlayClipMaskPatch(structureOverlay);
const productLockProtectMaskPatch = protectedPersonMask
const productLockProtectMask =
protectedPersonMask ||
(protectedPersonSide
? buildScaleAdjustProtectedPersonGeometryMask({
box: placement.sourceBox,
side: protectedPersonSide,
})
: null);
const productLockProtectMaskPatch = productLockProtectMask
? await buildScaleAdjustCompositeClipMaskPatch({
box: placement.sourceBox,
maskBuffer: dilateScaleAdjustStructureMask({
height: placement.sourceBox.height,
mask: protectedPersonMask,
mask: productLockProtectMask,
radius: Math.max(
2,
Math.round(
@ -2742,6 +2780,8 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
placedHeight,
placedWidth,
protectedPersonSide,
protectedPersonGeometryMaskApplied:
Boolean(productLockProtectMask) && !protectedPersonMask,
protectedPersonMaskApplied: Boolean(protectedPersonMask),
sameSizeCutout,
alphaBandingStats,
@ -2874,6 +2914,10 @@ function suppressScaleAdjustProtectedFurnitureDarkAlpha(params: {
return (
(sourceX >= sourceBox.width * 0.69 && sourceY >= sourceBox.height * 0.54) ||
(sourceX >= sourceBox.width * 0.58 && sourceY >= sourceBox.height * 0.7) ||
(sourceX >= sourceBox.width * 0.5 && sourceY >= sourceBox.height * 0.74) ||
(sourceX >= sourceBox.width * 0.56 &&
sourceY >= sourceBox.height * 0.58 &&
sourceY <= sourceBox.height * 0.78) ||
(sourceX >= sourceBox.width * 0.78 && sourceY >= sourceBox.height * 0.4) ||
(sourceX >= sourceBox.width * 0.91 && sourceY >= sourceBox.height * 0.26)
);
@ -2882,6 +2926,10 @@ function suppressScaleAdjustProtectedFurnitureDarkAlpha(params: {
return (
(sourceX <= sourceBox.width * 0.31 && sourceY >= sourceBox.height * 0.54) ||
(sourceX <= sourceBox.width * 0.42 && sourceY >= sourceBox.height * 0.7) ||
(sourceX <= sourceBox.width * 0.5 && sourceY >= sourceBox.height * 0.74) ||
(sourceX <= sourceBox.width * 0.44 &&
sourceY >= sourceBox.height * 0.58 &&
sourceY <= sourceBox.height * 0.78) ||
(sourceX <= sourceBox.width * 0.22 && sourceY >= sourceBox.height * 0.4) ||
(sourceX <= sourceBox.width * 0.09 && sourceY >= sourceBox.height * 0.26)
);