fix: improve structure locked scale drafts
This commit is contained in:
parent
d3cfb4a6b7
commit
ce4e056f20
@ -1149,6 +1149,51 @@ function isScaleAdjustLikelyWhiteFabricPixel(
|
||||
);
|
||||
}
|
||||
|
||||
function isScaleAdjustPersonLikePrompt(prompt: string) {
|
||||
const text = normalizeScaleAdjustModelText(prompt);
|
||||
return /person|people|human|woman|man|girl|boy|model|face|body|hand|arm|leg|clothing|人物|人像|真人|模特|女人|男人|女孩|男孩|小孩|脸|身体|手|胳膊|腿|衣服/.test(
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
function hasScaleAdjustPersonPixelSignal(params: {
|
||||
box: { left: number; top: number; width: number; height: number };
|
||||
raw: Buffer;
|
||||
width: number;
|
||||
}) {
|
||||
const { box, raw, width } = params;
|
||||
let sampled = 0;
|
||||
let skin = 0;
|
||||
let whiteFabric = 0;
|
||||
const step = Math.max(1, Math.floor(Math.min(box.width, box.height) / 260));
|
||||
|
||||
for (let localY = 0; localY < box.height; localY += step) {
|
||||
const y = box.top + localY;
|
||||
for (let localX = 0; localX < box.width; localX += step) {
|
||||
const x = box.left + localX;
|
||||
const rawIndex = getScaleAdjustRawPixelIndex(width, x, y);
|
||||
const r = raw[rawIndex] || 0;
|
||||
const g = raw[rawIndex + 1] || 0;
|
||||
const b = raw[rawIndex + 2] || 0;
|
||||
const { luma, saturation } = getScaleAdjustPixelStats(r, g, b);
|
||||
sampled += 1;
|
||||
if (isScaleAdjustLikelySkinPixel(r, g, b)) {
|
||||
skin += 1;
|
||||
} else if (
|
||||
isScaleAdjustLikelyWhiteFabricPixel(r, g, b, luma, saturation) &&
|
||||
luma < 242
|
||||
) {
|
||||
whiteFabric += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sampled <= 0) return false;
|
||||
const skinRatio = skin / sampled;
|
||||
const fabricRatio = whiteFabric / sampled;
|
||||
return skin >= 18 && skinRatio >= 0.0025 && fabricRatio >= 0.035;
|
||||
}
|
||||
|
||||
function estimateScaleAdjustBoxBackground(params: {
|
||||
box: { left: number; top: number; width: number; height: number };
|
||||
raw: Buffer;
|
||||
@ -1230,10 +1275,11 @@ function dilateScaleAdjustStructureMask(params: {
|
||||
|
||||
function buildScaleAdjustStructureInitialMask(params: {
|
||||
box: { left: number; top: number; width: number; height: number };
|
||||
includePersonPixels?: boolean;
|
||||
raw: Buffer;
|
||||
width: number;
|
||||
}) {
|
||||
const { box, raw, width } = params;
|
||||
const { box, includePersonPixels = false, raw, width } = params;
|
||||
const background = estimateScaleAdjustBoxBackground(params);
|
||||
const mask = new Uint8Array(box.width * box.height);
|
||||
|
||||
@ -1247,16 +1293,38 @@ function buildScaleAdjustStructureInitialMask(params: {
|
||||
const g = raw[rawIndex + 1] || 0;
|
||||
const b = raw[rawIndex + 2] || 0;
|
||||
const { luma, saturation } = getScaleAdjustPixelStats(r, g, b);
|
||||
if (isScaleAdjustLikelySkinPixel(r, g, b)) continue;
|
||||
if (isScaleAdjustLikelyWhiteFabricPixel(r, g, b, luma, saturation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const likelySkin = isScaleAdjustLikelySkinPixel(r, g, b);
|
||||
const likelyWhiteFabric = isScaleAdjustLikelyWhiteFabricPixel(
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
luma,
|
||||
saturation
|
||||
);
|
||||
const colorDistance = Math.sqrt(
|
||||
(r - background.r) ** 2 +
|
||||
(g - background.g) ** 2 +
|
||||
(b - background.b) ** 2
|
||||
);
|
||||
|
||||
if (includePersonPixels && likelySkin) {
|
||||
mask[localY * box.width + localX] = 255;
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
includePersonPixels &&
|
||||
likelyWhiteFabric &&
|
||||
luma < 246 &&
|
||||
(colorDistance > 12 || luma < background.luma - 4)
|
||||
) {
|
||||
mask[localY * box.width + localX] = 255;
|
||||
continue;
|
||||
}
|
||||
if (likelySkin) continue;
|
||||
if (likelyWhiteFabric) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const darkStructure = luma < Math.min(136, background.luma - 38);
|
||||
const saturatedStructure =
|
||||
saturation > 0.16 && luma < 218 && colorDistance > 38;
|
||||
@ -1596,14 +1664,22 @@ async function buildScaleAdjustMaskWashPatch(params: {
|
||||
}
|
||||
|
||||
async function buildScaleAdjustStructureLockedComposite(params: {
|
||||
includePersonPixels?: boolean;
|
||||
placement: ReturnType<typeof getScaleAdjustVisualGuidePlacement>;
|
||||
raw: Buffer;
|
||||
sourceBuffer: Buffer;
|
||||
sourceWidth: number;
|
||||
}) {
|
||||
const { placement, raw, sourceBuffer, sourceWidth } = params;
|
||||
const {
|
||||
includePersonPixels = false,
|
||||
placement,
|
||||
raw,
|
||||
sourceBuffer,
|
||||
sourceWidth,
|
||||
} = params;
|
||||
const initialMask = buildScaleAdjustStructureInitialMask({
|
||||
box: placement.sourceBox,
|
||||
includePersonPixels,
|
||||
raw,
|
||||
width: sourceWidth,
|
||||
});
|
||||
@ -1860,6 +1936,13 @@ async function buildScaleAdjustVisualLayoutGuideBuffer(params: {
|
||||
(targetWidthFactor > 1.08 || targetHeightFactor > 1.08);
|
||||
const structureLockedComposite = shouldUseStructureLock
|
||||
? await buildScaleAdjustStructureLockedComposite({
|
||||
includePersonPixels:
|
||||
isScaleAdjustPersonLikePrompt(region.prompt) ||
|
||||
hasScaleAdjustPersonPixelSignal({
|
||||
box: placement.sourceBox,
|
||||
raw: sourceRaw,
|
||||
width: sourceWidth,
|
||||
}),
|
||||
placement,
|
||||
raw: sourceRaw,
|
||||
sourceBuffer,
|
||||
@ -3154,7 +3237,8 @@ export async function POST(request: NextRequest) {
|
||||
: [];
|
||||
const useScaleAdjustPatchTargetDraftPrimary = Boolean(scaleAdjustPatchReference);
|
||||
const includeScaleAdjustPatchSourceReference =
|
||||
scaleAdjustPatchReference?.structureLockedDraft === true;
|
||||
Boolean(scaleAdjustPatchReference) &&
|
||||
scaleAdjustPatchReference?.structureLockedDraft !== true;
|
||||
const prompt = isScaleAdjustOperation
|
||||
? scaleAdjustPatchReference
|
||||
? buildScaleAdjustPatchPrompt(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user