-
Notifications
You must be signed in to change notification settings - Fork 2
/
embed_images_onnx.html
72 lines (58 loc) · 27.7 KB
/
embed_images_onnx.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!DOCTYPE html>
<html>
<head>
<title>Web/JS LiT Image Embedding Demo with ONNX Web Runtime</title>
</head>
<body>
<script src="./enable-threads.js"></script> <!-- a hack to add COEP/COOP headers which are needed for `SharedArrayBuffer`s and thread. Normally you would add these headers when serving this HTML file, but Github Pages doesn't allow setting these headers as of writing -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.17.0/dist/tf.min.js"></script> <!-- NOTE: tfjs is only used for loading the image and resizing/normalising it. Massively overkill to import the whole tfjs for this, but I'm lazy. -->
<script src="https://cdn.jsdelivr.net/npm/wasm-vips@0.0.2/lib/vips.js"></script>
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.11.0/dist/ort.js"></script>
<div>See browser console for model download and inference progress.</div>
<p><a href="https://github.com/josephrocca/lit-encoder-js">github repo</a> - <a href="https://huggingface.co/rocca/lit-web/tree/main">huggingface repo</a></p>
<script>
if(self.crossOriginIsolated) { // needs to be cross-origin-isolated to use wasm threads. you need to serve this html file with these two headers: https://web.dev/coop-coep/
ort.env.wasm.numThreads = navigator.hardwareConcurrency
}
async function start() {
console.log("Downloading model... (see network tab for progress)");
let modelPath = 'https://huggingface.co/rocca/lit-web/resolve/main/embed_images.onnx';
const session = await ort.InferenceSession.create(modelPath, { executionProviders: ["wasm"] });
console.log("Model loaded.");
// Trying bicubic resize using wasm-vips to see if it produces a more accurate output:
let imgBlob = await fetch(inputImg.src).then(r => r.blob());
imgBlob = await resizeAndCenterCrop(imgBlob, "cubic");
let newInputImg = new Image();
await new Promise(r => newInputImg.onload=r, newInputImg.src=URL.createObjectURL(imgBlob));
let img = tf.browser.fromPixels(newInputImg);
// img = tf.image.resizeBilinear(img, [224, 224]);
img = tf.sub(tf.div(tf.expandDims(img), 127.5), 1);
// img = img.transpose([0,2,1,3]); // swap rows/columns
console.log("Preprocessed image:", img, img.print(), img.dataSync()) // Should match Python preprocessed image (see conversion notebook): shape=(1, 224, 224, 3), array([[[[-0.18431371, -0.1372549 , -0.21568626], [-0.18431371, -0.1372549 , -0.21568626], [-0.18431371, -0.1372549 , -0.21568626], ..., [-0.19999999, -0.15294117, -0.23137254], [-0.19999999, -0.15294117, -0.23137254], [-0.19999999, -0.15294117, -0.23137254]], [[-0.18431371, -0.1372549 , -0.21568626], [-0.18431371, -0.1372549 , -0.21568626], [-0.18431371, -0.1372549 , -0.21568626], ..., [-0.19999999, -0.15294117, -0.23137254], [-0.19999999, -0.15294117, -0.23137254], [-0.19999999, -0.15294117, -0.23137254]], [[-0.19215685, -0.14509803, -0.2235294 ], [-0.19215685, -0.14509803, -0.2235294 ], [-0.18431371, -0.1372549 , -0.21568626], ..., [-0.19999999, -0.15294117, -0.23137254], [-0.19999999, -0.15294117, -0.23137254], [-0.19999999, -0.15294117, -0.23137254]], ..., [[ 0.70980394, 0.34901965, 0.1686275 ], [ 0.7019608 , 0.3411765 , 0.16078436], [ 0.69411767, 0.33333337, 0.15294123], ..., [-0.05882353, -0.25490195, -0.41176468], [-0.01960784, -0.21568626, -0.372549 ], [-0.01176471, -0.20784312, -0.36470586]], [[ 0.7176471 , 0.35686278, 0.17647064], [ 0.7019608 , 0.3411765 , 0.16078436], [ 0.6862745 , 0.32549024, 0.14509809], ..., [-0.23921567, -0.4352941 , -0.5921569 ], [-0.21568626, -0.41176468, -0.5686275 ], [-0.05882353, -0.25490195, -0.41176468]], [[ 0.7176471 , 0.35686278, 0.17647064], [ 0.7019608 , 0.3411765 , 0.16078436], [ 0.6862745 , 0.32549024, 0.14509809], ..., [-0.19999999, -0.3960784 , -0.5529412 ], [-0.35686272, -0.5529412 , -0.70980394], [-0.26274508, -0.4588235 , -0.6156863 ]]]], dtype=float32)
let float32RgbData = img.dataSync();
const feeds = {'images': new ort.Tensor('float32', float32RgbData, [1,224,224,3])};
console.log("Running inference...");
const results = await session.run(feeds);
console.log("Finished inference.");
const data = results["Identity_1:0"].data;
console.log(`data of result tensor 'output'`, data); // Should match this Python output: <tf.Tensor: shape=(1, 768), dtype=float32, numpy= array([[-5.55288605e-02, 5.64340614e-02, -2.53345165e-02, -7.04571372e-03, -4.43741232e-02, -9.98641457e-03, 1.47062605e-02, -1.28184434e-03, -4.88287956e-03, 3.44051234e-02, -3.47652510e-02, -2.54354160e-02, -1.67460516e-02, -4.55446541e-03, -2.95176860e-02, 1.50395669e-02, 1.91923082e-02, -2.26781471e-03, 5.53558804e-02, -2.05553714e-02, -1.90312341e-02, 3.07557285e-02, -1.34337973e-02, -2.51099486e-02, 4.73540509e-03, 7.24522024e-02, -2.76858658e-02, 1.33900195e-02, -5.63910324e-03, 7.59580508e-02, -2.10811291e-02, -4.26671468e-02, 4.40267362e-02, -8.98994133e-03, -2.72203200e-02, 9.45691671e-03, -4.53936607e-02, -5.14366031e-02, -1.60149615e-02, -3.43620256e-02, 1.67564414e-02, -6.35175966e-03, 2.28999201e-02, -1.53777329e-02, -6.26899628e-03, -2.14609914e-02, 2.90533844e-02, -1.50994482e-02, -2.10201330e-02, -1.38329370e-02, -4.49863449e-02, -4.41115126e-02, -2.19534207e-02, -3.32826795e-03, 9.05098692e-02, 6.66638389e-02, 5.03067635e-02, -1.52756488e-02, 8.25127438e-02, 4.60092500e-02, -3.88483293e-02, 2.42163371e-02, 7.83452764e-03, 1.45086590e-02, -8.31264909e-03, -9.67319589e-03, 2.75635328e-02, 4.29737456e-02, 4.05971222e-02, -1.91829894e-02, 4.11723293e-02, 4.37577814e-02, 3.78900208e-02, 3.83098759e-02, -4.61554062e-03, -4.68678400e-02, 3.37354243e-02, -8.43731780e-03, 3.13742533e-02, -7.89565146e-02, -3.10057085e-02, 2.45358255e-02, 1.89499855e-02, -7.09262851e-04, -2.53144978e-03, 4.16370761e-03, 2.07571313e-02, -3.48992683e-02, 2.09441911e-02, -1.71091855e-02, 3.65436785e-02, -3.45533863e-02, 2.58497763e-02, 3.44194733e-02, -9.19138722e-04, 1.17515204e-02, 1.68126654e-02, -5.86700775e-02, -3.39939632e-03, -3.10825147e-02, -2.30307784e-02, -3.11668571e-02, -5.54464711e-03, 1.37866680e-02, 2.61747614e-02, 4.16784957e-02, 4.34378535e-03, -3.82242799e-02, 1.98121578e-03, -3.98717746e-02, -5.11223041e-02, 4.01592329e-02, -1.23500554e-02, -3.64161655e-02, -2.87640058e-02, -2.88403723e-02, 1.57118309e-02, -3.85608301e-02, -6.18323199e-02, -6.34001009e-03, -4.01449716e-03, 1.18544186e-02, 6.55796751e-02, -1.48253108e-03, -7.78398067e-02, 3.46688628e-02, 2.10667867e-02, -3.33210342e-02, -3.08420677e-02, 6.74544275e-02, 3.83570008e-02, -4.88578342e-02, 8.71998630e-03, -2.31635049e-02, 5.25287772e-03, -4.09497023e-02, 4.00403421e-03, -7.64907803e-04, 3.34092602e-02, -1.44934910e-03, 3.24835069e-02, -1.50138773e-02, -4.36986126e-02, -4.87227254e-02, 3.47975791e-02, 4.59121447e-03, 1.81808528e-02, 3.19259763e-02, -4.66678701e-02, 2.84910537e-02, 2.74117235e-02, -8.53077844e-02, 6.95680967e-03, 5.90133946e-03, 6.67735115e-02, 5.05174929e-03, 4.99259159e-02, -3.42527628e-02, 3.89683209e-02, -5.66338412e-02, 1.01811029e-02, 6.46993592e-02, -6.13492876e-02, 3.88713591e-02, -1.25983823e-03, 2.36083381e-02, -3.89135256e-02, 4.64939699e-02, -2.11299490e-02, 8.57634172e-02, 2.70849168e-02, -7.15621784e-02, -9.73020215e-03, 6.80590197e-02, 4.73974608e-02, 3.44545953e-02, 2.65838262e-02, -2.04003435e-02, -1.57233160e-02, 4.12059063e-03, 9.63761378e-03, 5.35897799e-02, 6.41301796e-02, -2.71239821e-02, -3.29721980e-02, 9.67182964e-03, 3.94103192e-02, 4.11344729e-02, 3.39421853e-02, -9.56541020e-03, 3.01231071e-02, -1.59552488e-02, -3.33356597e-02, -2.36353427e-02, 7.57023543e-02, -1.33333057e-02, 6.09955676e-02, 2.73746420e-02, 1.64279528e-03, 3.46935168e-02, -1.46181146e-02, -1.49208633e-02, 1.26836235e-02, -9.91479866e-03, -3.51516567e-02, -7.98327290e-03, 4.35497239e-02, 4.10020053e-02, 1.62350256e-02, -3.61766666e-02, 2.52225175e-02, -4.29343581e-02, -1.14111351e-02, 2.43643336e-02, 3.08839558e-03, 1.79989391e-03, 4.47691865e-02, 1.37758637e-02, 2.54659541e-02, -6.85707806e-03, 2.00292673e-02, -2.84691826e-02, 2.29235250e-03, -2.05723662e-02, 1.09174941e-02, -6.43825084e-02, -3.79503109e-02, -9.41415259e-04, -3.61803547e-02, -7.46927224e-03, -1.30075298e-03, 3.26463161e-03, -7.26976898e-03, -8.97389429e-04, -3.41747403e-02, 6.47894368e-02, -6.21959521e-03, 9.80529655e-03, -9.07410681e-03, 2.03307196e-02, 6.64004171e-03, 8.13197996e-03, 3.40018123e-02, -2.08798591e-02, 3.13870311e-02, 2.03678105e-02, -6.00338690e-02, 3.58492788e-03, -2.55744942e-02, -1.17170140e-02, -5.84120229e-02, -2.04234757e-02, 9.28296074e-02, -1.04199117e-02, 6.05984703e-02, -1.99247655e-02, -2.92796385e-03, -3.74304354e-02, 4.92083235e-03, 4.02596556e-02, -3.31737772e-02, 3.69565077e-02, 2.19649505e-02, 1.84168816e-02, 2.97339112e-02, -2.14743484e-02, 6.51975051e-02, -6.74007088e-03, 3.69749591e-02, 9.03268997e-03, 1.43465884e-02, 4.98560444e-02, -5.17466515e-02, 9.53856111e-02, -1.54915405e-02, 2.93457843e-02, -3.62743884e-02, 2.31916308e-02, 7.09446473e-03, 6.10102639e-02, -2.09006649e-02, -6.01934316e-03, 1.37332417e-02, 2.68461909e-02, 4.84039895e-02, 7.69268908e-03, 5.16691478e-03, -8.34577233e-02, -3.94475162e-02, 2.17310525e-02, 3.12906168e-02, 4.98158038e-02, -2.73350198e-02, 2.74802912e-02, 4.49799746e-02, -5.06620631e-02, -6.91863149e-03, 2.12936439e-02, -5.95555194e-02, -2.17335839e-02, -1.53381638e-02, -1.34454472e-02, -2.52176002e-02, 2.13016476e-03, 1.12128081e-02, -1.13126393e-02, -2.63409149e-02, 4.43314351e-02, 3.74056958e-02, -3.30872387e-02, 3.28797698e-02, 5.72820101e-03, 7.71122286e-03, -4.28940617e-02, 1.92545820e-02, -1.01652266e-02, 4.47919592e-02, 3.41679230e-02, -8.89962539e-03, -6.24953099e-02, 5.22015654e-02, 1.47697441e-02, -1.00187294e-01, -9.87493433e-03, -3.28931548e-02, -4.42514895e-03, 4.52178977e-02, -3.66132446e-02, 4.69694212e-02, -4.63780016e-04, -3.48447114e-02, 5.73270349e-03, 2.34761387e-02, 5.53485565e-02, 3.77383716e-02, 6.87709376e-02, -4.51187566e-02, 1.45925879e-02, -6.32281527e-02, -4.59706821e-02, -9.94751789e-03, -1.98460140e-04, 2.07195878e-02, 1.78694669e-02, -2.48973556e-02, 2.72764005e-02, -2.28066240e-02, 4.63856161e-02, -4.06439044e-02, -8.19210410e-02, -6.21822216e-02, -2.06129812e-02, -9.51991230e-03, -3.89186963e-02, 5.40457219e-02, 6.00668266e-02, 1.19655775e-02, -4.83530313e-02, -3.12056486e-02, -5.61766559e-03, 7.07702637e-02, -8.04154202e-02, -1.08817378e-02, -2.62581594e-02, -5.17709590e-02, -7.21407011e-02, 4.22283746e-02, -8.37194268e-03, 2.09423304e-02, -8.36069360e-02, 9.36375652e-03, 9.32646581e-05, -3.53276245e-02, -3.27506848e-02, -4.30693924e-02, 2.52761338e-02, 9.89051256e-03, 7.54159167e-02, -1.46941245e-02, -2.14762241e-03, 3.89660429e-03, 1.45905092e-03, -2.19418164e-02, 3.67620215e-02, -4.14361618e-02, -6.05166703e-03, 1.76760480e-02, 4.11533937e-02, 2.40210071e-02, -2.41764057e-02, 2.88283378e-02, -5.53069860e-02, -5.95534407e-02, -3.34911444e-03, 4.69012298e-02, 3.46254073e-02, -5.81116974e-03, 4.23124805e-02, -6.06447458e-02, 2.69575007e-02, 1.16482517e-02, 2.69681923e-02, -5.94366118e-02, 3.00677139e-02, 1.88053977e-02, 3.48632014e-03, 6.97961589e-03, 2.36018561e-02, 8.19104761e-02, -3.89042161e-02, -9.51547700e-04, -2.85978522e-02, -7.68615007e-02, -2.10982841e-02, 3.08274734e-03, 2.94836331e-02, 2.94955578e-02, -1.89413521e-02, -4.19611409e-02, -2.64922120e-02, 7.08568469e-02, -1.57028753e-02, 1.54392831e-02, -3.04722264e-02, -2.99727935e-02, 1.23983137e-02, 8.71629193e-02, 3.37476470e-02, -5.16272038e-02, 6.78137410e-03, 6.16276115e-02, -1.93970688e-02, 5.92741035e-02, 7.24173188e-02, 3.72917354e-02, -2.29027178e-02, 2.64072102e-02, 3.71082798e-02, -1.26907323e-02, 8.13377835e-03, 6.78300634e-02, -2.68073343e-02, -2.19536722e-02, -1.96026620e-02, -3.99302877e-02, -4.07159738e-02, 3.12540010e-02, -1.63130686e-02, -2.60993429e-02, -1.47612635e-02, -3.96942832e-02, -9.68617294e-03, 4.06307243e-02, 3.71432491e-02, 1.27425967e-02, 8.67543183e-03, 2.25664098e-02, -1.56813040e-02, 2.47509102e-03, 1.85762290e-02, 6.59866119e-03, 1.02484124e-02, 8.68644565e-03, -3.71638536e-02, -4.53539453e-02, 4.61705141e-02, 1.12808002e-02, 7.40791112e-02, 1.38988963e-03, -5.41768456e-03, -1.60796363e-02, -4.51780818e-02, -8.42829645e-02, -9.67159495e-03, -3.19003649e-02, 4.93971910e-03, -6.16185479e-02, -5.37701547e-02, 3.32410261e-02, -4.94721867e-02, 4.24431041e-02, 4.80356142e-02, 1.03348428e-02, 1.76328532e-02, 1.30198468e-02, -1.30744176e-02, 1.60950348e-02, 1.54092349e-02, 4.04075999e-03, -2.76297200e-02, -2.06076559e-02, -1.04464004e-02, -1.09284837e-02, 6.85348883e-02, -6.49712863e-04, 1.51596474e-03, 4.73303869e-02, -2.51297746e-02, 7.47945718e-03, -3.20643969e-02, 2.26924587e-02, -6.67890310e-02, 5.54981455e-02, -1.74220297e-02, 2.92003248e-02, -9.54182073e-02, -3.09219845e-02, 2.43839324e-02, -4.16209139e-02, 4.00904305e-02, -3.68539505e-02, -1.27100078e-02, -2.12715045e-02, -2.71928404e-02, -2.58380994e-02, -6.09865971e-02, -6.56279102e-02, 3.36726718e-02, 3.93014252e-02, 1.36637585e-02, 3.24850604e-02, 6.37986362e-02, -3.37560661e-02, 3.19418660e-03, 3.22878845e-02, 3.55098508e-02, -7.91002810e-03, -1.41184428e-03, -2.28453856e-02, 2.63372269e-02, 2.27970742e-02, -1.86122786e-02, -2.18473058e-02, -4.63546216e-02, 8.46941117e-03, 2.57165283e-02, 2.26551034e-02, 1.89750839e-03, -2.50047626e-04, -2.21450031e-02, -7.51781091e-02, 6.25660643e-02, -2.95744538e-02, -5.01605822e-03, 1.07241850e-02, 4.90169935e-02, 3.71685810e-03, 3.41197080e-03, 7.81860668e-03, -1.03105148e-02, 1.15358802e-02, -1.02553917e-02, -3.80068645e-02, 3.83781344e-02, 4.14294787e-02, 4.17613424e-02, -2.78428961e-02, -3.13760601e-02, -2.00225040e-02, 1.09527884e-02, 4.48935898e-04, 2.54259855e-02, 2.26195101e-02, 5.98334558e-02, -5.86843714e-02, 3.78140360e-02, -2.21908260e-02, -2.45137210e-03, 3.01031992e-02, -1.38568962e-02, 3.95525666e-03, -4.64336984e-02, 3.24312155e-03, 3.62765603e-02, 1.07628256e-02, -3.83002460e-02, -7.47316256e-02, -5.80311604e-02, 1.91689413e-02, 1.22936266e-02, 3.40336841e-03, -3.97081673e-02, 3.65593731e-02, -2.15923712e-02, 1.18821086e-02, -5.71375675e-02, 3.47678475e-02, -4.61607939e-03, 8.86810124e-02, -2.71564033e-02, -4.14683297e-03, 6.32964075e-02, -2.29251403e-02, 3.72919552e-02, -2.26218533e-02, 4.14885953e-02, -9.15344656e-02, 1.46714132e-02, 3.94211859e-02, 8.25076364e-03, -6.76905550e-03, 5.03413603e-02, -4.77418453e-02, 1.07817620e-03, 3.62619311e-02, -6.10567257e-02, 1.62884481e-02, 6.47325581e-03, 2.76953746e-02, -8.39184746e-02, -3.94960940e-02, 4.12094854e-02, -5.52113354e-02, 8.49257782e-02, 9.76075139e-03, -3.63970809e-02, -7.36794397e-02, 1.31604448e-02, 4.21905294e-02, -6.49708789e-03, -1.58983264e-02, -1.91671494e-02, -1.42192189e-02, -6.29734918e-02, 2.04359684e-02, 4.01044488e-02, 1.04645295e-02, 2.14620586e-03, 7.68511510e-03, 5.00545721e-04, -3.38501595e-02, -5.29781282e-02, -2.26770975e-02, 6.38152957e-02, -2.33975295e-02, -2.32661199e-02, -1.70470867e-02, -4.02799509e-02, 4.24818061e-02, 1.51810898e-02, 5.46051413e-02, 4.72050905e-02, -1.63749345e-02, 3.03662326e-02, 1.39182415e-02, -5.08213155e-02, 4.74495925e-02, -3.83132584e-02, -4.02431525e-02, -2.13898122e-02, -1.89822614e-02, -1.41115487e-02, -3.44667435e-02, 3.31531949e-02, -1.35711310e-02, 4.50920425e-02, -2.59729419e-02, 4.10260893e-02, 5.14373481e-02, 3.29043418e-02, 2.75134183e-02, 2.95161139e-02, -7.27142990e-02, 4.50623333e-02, 2.78604520e-03, -2.93508936e-02, 4.26538214e-02, -5.62053099e-02, -3.40348817e-02, -1.51766064e-02, -4.03201953e-03, 3.14128511e-02, -2.35591852e-03, -9.38047364e-04, -4.18359786e-02, 6.15496421e-03, 3.02484748e-03, 5.37108444e-03, 3.77169736e-02, 3.40035111e-02, -2.48965118e-02, -3.57956327e-02, -1.31143453e-02, -8.64162855e-03, 1.39521565e-02, 3.67682390e-02, -3.97949778e-02, 1.31267160e-02, -1.39813162e-02, -6.94726631e-02, 4.70671803e-02, 5.25823124e-02, -3.23877641e-04, -3.97794545e-02, -1.92869622e-02, 6.20311126e-02, 3.82961817e-02, 8.89877155e-02, -3.90683375e-02, 2.93353908e-02, -7.01931119e-02, -2.43512867e-03, -6.11148067e-02, 1.17370682e-02, 2.42216960e-02, -1.24126142e-02, 4.69552306e-03, -1.56393219e-02, -2.46463157e-03, 1.31977291e-03, -8.14838260e-02, -5.15358932e-02, -1.22746099e-02, 1.35188699e-02, -5.85810747e-03, 5.91081977e-02, -2.00925511e-03, -6.53413460e-02, -4.33194655e-04, 7.01681944e-03, -6.29075011e-03, -4.71504182e-02, -9.67840943e-03, 2.74118856e-02, -4.52952087e-02, 6.31998405e-02, -2.60138093e-03, -6.51679859e-02, -1.83278602e-02, 3.68211530e-02, -2.39318162e-02, -5.46160042e-02, 1.73179433e-02, -4.49317209e-02, -2.23545842e-02, 4.63705603e-03, 2.85355328e-03, -1.62762068e-02, -3.83532792e-03, -2.29063574e-02, -2.67444961e-02, -2.65146159e-02, 8.54273792e-03, -2.14673579e-02, -2.83040982e-02, -2.81662606e-02, -5.04181273e-02, 3.35215181e-02, -6.09818138e-02, -2.88233664e-02, -1.81329325e-02, -6.11266643e-02, -1.82599705e-02, -1.64896585e-02, -2.10631788e-02, -1.15908321e-03, 1.82249583e-02, -1.74278999e-03, 2.23693661e-02, -5.00599330e-04, 1.03008409e-03, 7.70662073e-03, 3.08368690e-02, 8.07732344e-04, -4.29923162e-02, -7.47650936e-02, -2.77654827e-03, -4.01279610e-03]], dtype=float32)>
}
async function resizeAndCenterCrop(blob, resizeType="cubic", size=224) {
if(!window.vips) window.vips = await Vips();
// resize types available: cubic, linear, lanczos2, lanczos3, nearest, mitchell
let im1 = vips.Image.newFromBuffer(await blob.arrayBuffer());
// Resize so smallest side is `size` px:
const scale = 224 / Math.min(im1.height, im1.width);
let im2 = im1.resize(scale, { kernel: vips.Kernel[resizeType] });
// crop to `size` x `size`:
let left = (im2.width - size) / 2;
let top = (im2.height - size) / 2;
let im3 = im2.crop(left, top, size, size)
let outBuffer = new Uint8Array(im3.writeToBuffer('.png'));
im1.delete(), im2.delete(), im3.delete();
return new Blob([outBuffer], { type: 'image/png' });
}
</script>
<img id="inputImg" onload="window.start()" style="max-height:300px" src="data:image/jpeg;base64,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">
</body>
</html>