fix(heal): resolve adjacent objects texture leak and overwriting by clustering and progressive masking

This commit is contained in:
2026-10-14 16:15:00 +07:00
parent a24f000ead
commit 1fe31c35a4
3 changed files with 72 additions and 13 deletions
+9 -5
View File
@@ -238,6 +238,8 @@ export function fastLocalInpaint(
out[p + 1] = cg;
out[p + 2] = cb;
out[p + 3] = 255;
} else {
out[i * 4 + 3] = 0;
}
}
return out;
@@ -323,18 +325,20 @@ export function fastLocalInpaint(
return (seed / 0x7fffffff) * 2 - 1;
}
// 5. Output
// 5. Output: only hole pixels are opaque; outside hole is transparent (alpha = 0)
for (let y = 0; y < h; y++) {
const row = y * w;
for (let x = 0; x < w; x++) {
const idx = row + x;
const p = idx * 4;
if (hole[idx]) {
const p = idx * 4;
const grain = noiseAmp > 0.5 ? prng() * noiseAmp : 0;
out[p] = Math.max(0, Math.min(255, Math.round(fR[idx] + grain)));
out[p + 1] = Math.max(0, Math.min(255, Math.round(fG[idx] + grain)));
out[p + 2] = Math.max(0, Math.min(255, Math.round(fB[idx] + grain)));
out[p + 3] = 255;
} else {
out[p + 3] = 0;
}
}
}
@@ -471,14 +475,14 @@ export async function inpaintCrop(
const tensor = out[session.outputNames[0]];
const oplane = w * h;
const data = tensor.data as Uint8Array;
// Back to RGBA, opaque: the crop covers the frame, which has no transparency
// of its own to carry.
// Back to RGBA: only pixels inside the hole (mask[i] === 0) are opaque;
// pixels outside the hole are transparent so drawing the patch never overwrites adjacent clusters.
const patch = new Uint8Array(4 * w * h);
for (let i = 0; i < oplane; i++) {
patch[i * 4] = data[i];
patch[i * 4 + 1] = data[oplane + i];
patch[i * 4 + 2] = data[2 * oplane + i];
patch[i * 4 + 3] = 255;
patch[i * 4 + 3] = mask[i] === 0 ? 255 : 0;
}
try {
in0.dispose?.();