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: {
|
function estimateScaleAdjustBoxBackground(params: {
|
||||||
box: { left: number; top: number; width: number; height: number };
|
box: { left: number; top: number; width: number; height: number };
|
||||||
raw: Buffer;
|
raw: Buffer;
|
||||||
@ -1230,10 +1275,11 @@ function dilateScaleAdjustStructureMask(params: {
|
|||||||
|
|
||||||
function buildScaleAdjustStructureInitialMask(params: {
|
function buildScaleAdjustStructureInitialMask(params: {
|
||||||
box: { left: number; top: number; width: number; height: number };
|
box: { left: number; top: number; width: number; height: number };
|
||||||
|
includePersonPixels?: boolean;
|
||||||
raw: Buffer;
|
raw: Buffer;
|
||||||
width: number;
|
width: number;
|
||||||
}) {
|
}) {
|
||||||
const { box, raw, width } = params;
|
const { box, includePersonPixels = false, raw, width } = params;
|
||||||
const background = estimateScaleAdjustBoxBackground(params);
|
const background = estimateScaleAdjustBoxBackground(params);
|
||||||
const mask = new Uint8Array(box.width * box.height);
|
const mask = new Uint8Array(box.width * box.height);
|
||||||
|
|
||||||
@ -1247,16 +1293,38 @@ function buildScaleAdjustStructureInitialMask(params: {
|
|||||||
const g = raw[rawIndex + 1] || 0;
|
const g = raw[rawIndex + 1] || 0;
|
||||||
const b = raw[rawIndex + 2] || 0;
|
const b = raw[rawIndex + 2] || 0;
|
||||||
const { luma, saturation } = getScaleAdjustPixelStats(r, g, b);
|
const { luma, saturation } = getScaleAdjustPixelStats(r, g, b);
|
||||||
if (isScaleAdjustLikelySkinPixel(r, g, b)) continue;
|
const likelySkin = isScaleAdjustLikelySkinPixel(r, g, b);
|
||||||
if (isScaleAdjustLikelyWhiteFabricPixel(r, g, b, luma, saturation)) {
|
const likelyWhiteFabric = isScaleAdjustLikelyWhiteFabricPixel(
|
||||||
continue;
|
r,
|
||||||
}
|
g,
|
||||||
|
b,
|
||||||
|
luma,
|
||||||
|
saturation
|
||||||
|
);
|
||||||
const colorDistance = Math.sqrt(
|
const colorDistance = Math.sqrt(
|
||||||
(r - background.r) ** 2 +
|
(r - background.r) ** 2 +
|
||||||
(g - background.g) ** 2 +
|
(g - background.g) ** 2 +
|
||||||
(b - background.b) ** 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 darkStructure = luma < Math.min(136, background.luma - 38);
|
||||||
const saturatedStructure =
|
const saturatedStructure =
|
||||||
saturation > 0.16 && luma < 218 && colorDistance > 38;
|
saturation > 0.16 && luma < 218 && colorDistance > 38;
|
||||||
@ -1596,14 +1664,22 @@ async function buildScaleAdjustMaskWashPatch(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function buildScaleAdjustStructureLockedComposite(params: {
|
async function buildScaleAdjustStructureLockedComposite(params: {
|
||||||
|
includePersonPixels?: boolean;
|
||||||
placement: ReturnType<typeof getScaleAdjustVisualGuidePlacement>;
|
placement: ReturnType<typeof getScaleAdjustVisualGuidePlacement>;
|
||||||
raw: Buffer;
|
raw: Buffer;
|
||||||
sourceBuffer: Buffer;
|
sourceBuffer: Buffer;
|
||||||
sourceWidth: number;
|
sourceWidth: number;
|
||||||
}) {
|
}) {
|
||||||
const { placement, raw, sourceBuffer, sourceWidth } = params;
|
const {
|
||||||
|
includePersonPixels = false,
|
||||||
|
placement,
|
||||||
|
raw,
|
||||||
|
sourceBuffer,
|
||||||
|
sourceWidth,
|
||||||
|
} = params;
|
||||||
const initialMask = buildScaleAdjustStructureInitialMask({
|
const initialMask = buildScaleAdjustStructureInitialMask({
|
||||||
box: placement.sourceBox,
|
box: placement.sourceBox,
|
||||||
|
includePersonPixels,
|
||||||
raw,
|
raw,
|
||||||
width: sourceWidth,
|
width: sourceWidth,
|
||||||
});
|
});
|
||||||
@ -1860,6 +1936,13 @@ async function buildScaleAdjustVisualLayoutGuideBuffer(params: {
|
|||||||
(targetWidthFactor > 1.08 || targetHeightFactor > 1.08);
|
(targetWidthFactor > 1.08 || targetHeightFactor > 1.08);
|
||||||
const structureLockedComposite = shouldUseStructureLock
|
const structureLockedComposite = shouldUseStructureLock
|
||||||
? await buildScaleAdjustStructureLockedComposite({
|
? await buildScaleAdjustStructureLockedComposite({
|
||||||
|
includePersonPixels:
|
||||||
|
isScaleAdjustPersonLikePrompt(region.prompt) ||
|
||||||
|
hasScaleAdjustPersonPixelSignal({
|
||||||
|
box: placement.sourceBox,
|
||||||
|
raw: sourceRaw,
|
||||||
|
width: sourceWidth,
|
||||||
|
}),
|
||||||
placement,
|
placement,
|
||||||
raw: sourceRaw,
|
raw: sourceRaw,
|
||||||
sourceBuffer,
|
sourceBuffer,
|
||||||
@ -3154,7 +3237,8 @@ export async function POST(request: NextRequest) {
|
|||||||
: [];
|
: [];
|
||||||
const useScaleAdjustPatchTargetDraftPrimary = Boolean(scaleAdjustPatchReference);
|
const useScaleAdjustPatchTargetDraftPrimary = Boolean(scaleAdjustPatchReference);
|
||||||
const includeScaleAdjustPatchSourceReference =
|
const includeScaleAdjustPatchSourceReference =
|
||||||
scaleAdjustPatchReference?.structureLockedDraft === true;
|
Boolean(scaleAdjustPatchReference) &&
|
||||||
|
scaleAdjustPatchReference?.structureLockedDraft !== true;
|
||||||
const prompt = isScaleAdjustOperation
|
const prompt = isScaleAdjustOperation
|
||||||
? scaleAdjustPatchReference
|
? scaleAdjustPatchReference
|
||||||
? buildScaleAdjustPatchPrompt(
|
? buildScaleAdjustPatchPrompt(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user