This function used to remove background from a selfie image, and this runs on a mobile device, and if this function runs more than five times consecutively, it throws following error,
E/Capacitor/Console: File: http://localhost/vendor-es2015.js - Line 61524 - Msg: ERROR Error: Uncaught (in promise): RuntimeError: memory access out of bounds
RuntimeError: memory access out of bounds
at http://localhost/assets/tf-wasm/tfjs-backend-wasm.wasm:wasm-function[9]:0xaef
at http://localhost/assets/tf-wasm/tfjs-backend-wasm.wasm:wasm-function[180]:0x16f01
at BackendWasm.disposeData (http://localhost/editor-editor-module-es2015.js:84977:23)
at Engine.disposeTensor (http://localhost/editor-editor-module-es2015.js:82856:26)
at Tensor.dispose (http://localhost/editor-editor-module-es2015.js:51006:21)
at Engine.endScope (http://localhost/editor-editor-module-es2015.js:82975:24)
at http://localhost/editor-editor-module-es2015.js:82479:71
at Engine.scopedRun (http://localhost/editor-editor-module-es2015.js:82495:13)
at Engine.tidy (http://localhost/editor-editor-module-es2015.js:82479:21)
at tidy (http://localhost/editor-editor-module-es2015.js:124425:59)
And the function is following,
async removeBackGround(imageData) {
const ref_size = 512;
try {
let tensor: any = tf.browser.fromPixels(imageData, 3);
const offset = tf.scalar(127.5);
tensor = tf.cast(tensor, "float32");
tensor = tf.sub(tensor, offset);
tensor = tf.div(tensor, offset);
tensor = tf.image.resizeBilinear(tensor, [ref_size, ref_size]);
tensor = tf.expandDims(tensor);
let res: any = await this.model.predict(tensor);
res = tf.image.resizeBilinear(res, [imageData.height, imageData.width]);
res = tf.squeeze(res);
// let matcanvas: any = document.getElementById("backgroundCanvas");
let matcanvas = document.createElement("canvas");
matcanvas.width = imageData.width + 10 * 2;
matcanvas.height = imageData.height + 10 * 2;
console.log('matcanvas.width', matcanvas.width);
console.log('matcanvas.height', matcanvas.height);
// tf.browser.toPixels(res, matcanvas);
res = tf.mul(res, offset);
res = tf.add(res, offset);
res = tf.cast(res, "int32");
let arr = res.dataSync();
let imageDataWithOutAlpha = this.removeAlpha(imageData.data);
let idx = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] < 200) {
imageDataWithOutAlpha[idx] = 255;
imageDataWithOutAlpha[idx + 1] = 255;
imageDataWithOutAlpha[idx + 2] = 255;
}
idx += 3;
}
let imageDataBackWithAlpha = this.addAlpha(imageDataWithOutAlpha);
let buffer: any = new Uint8ClampedArray(imageDataBackWithAlpha);
const ctx: any = matcanvas.getContext("2d", { antialias: false });
ctx.fillStyle = "#c3c3c3";
// fill it with border colour
ctx.fillRect(0, 0, matcanvas.width, matcanvas.height);
var idata = ctx.createImageData(imageData.width, imageData.height);
idata.data.set(buffer);
ctx.putImageData(idata, 10, 10)
let bgRemoved = matcanvas.toDataURL();
return bgRemoved;
} catch (error) {
throw error
} finally {
tf.disposeVariables();
tf.dispose();
alert('TF disposed !')
}
}