in src/nodes/client/background-removal.ts [85:159]
async runWithInputs(inputs: Inputs, services: Services) {
const { image, modelid, quantized, device } = inputs;
const _modelid = modelid?.trim();
if (!image?.canvasId) {
// No input node
this.dispatchEvent(
new CustomEvent("outputs", { detail: { foreground: null } })
);
return;
}
if (this.cachedResult && compareObjects(this.cachedInput, inputs)) {
this.dispatchEvent(
new CustomEvent("outputs", {
detail: { foreground: this.cachedResult },
})
);
return;
}
this.cachedInput = inputs;
// Clear masks
// this.masks.innerHTML = '';
const canvas = services.resourceService.get(
image.canvasId
) as HTMLCanvasElement;
const data = canvas.toDataURL();
const [model, processor] = await this.getInstance(
_modelid,
quantized,
device
);
// TODO: .fromCanvas() method
const i = await RawImage.fromURL(data);
// Preprocess image
const { pixel_values } = await processor(i);
// Predict alpha matte
const { output } = await model({ input: pixel_values });
// Resize mask back to original size
const mask = await RawImage.fromTensor(
output[0].mul(255).to("uint8")
).resize(i.width, i.height);
// Create new canvas
const c = document.createElement("canvas");
c.width = i.width;
c.height = i.height;
const ctx = c.getContext("2d")!;
// Draw original image output to canvas
ctx.drawImage(i.toCanvas(), 0, 0);
// Update alpha channel
const pixelData = ctx.getImageData(0, 0, i.width, i.height);
for (let i = 0; i < mask.data.length; ++i) {
pixelData.data[4 * i + 3] = mask.data[i];
}
ctx.putImageData(pixelData, 0, 0);
const out = {
canvasId: services.resourceService.put(c),
};
const detail: Outputs = { foreground: out };
this.cachedResult = out;
this.dispatchEvent(new CustomEvent("outputs", { detail: detail }));
}