|
import { AutoProcessor, RawImage, AutoModel } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers'; |
|
|
|
const status = document.getElementById('status'); |
|
const fileSelect = document.getElementById('file-select'); |
|
const imageContainer = document.getElementById('image-container'); |
|
const outputContainer = document.getElementById('output-container'); |
|
|
|
status.textContent = 'Loading model...'; |
|
let startTime = null; |
|
let endTime = null; |
|
|
|
|
|
const model = await AutoModel.from_pretrained('Xenova/modnet-onnx', { quantized: false }); |
|
const processor = await AutoProcessor.from_pretrained('Xenova/modnet-onnx'); |
|
|
|
status.textContent = 'Ready'; |
|
|
|
const url = 'https://images.pexels.com/photos/5965592/pexels-photo-5965592.jpeg?auto=compress&cs=tinysrgb&w=1024'; |
|
function useRemoteImage(url) { |
|
const image = document.createElement('img'); |
|
image.crossOrigin = "anonymous"; |
|
image.src = url; |
|
imageContainer.appendChild(image); |
|
setTimeout(() => start(url), 0) |
|
} |
|
useRemoteImage(url) |
|
|
|
fileSelect.addEventListener('change', function (e) { |
|
const file = e.target.files[0]; |
|
if (!file) { |
|
return; |
|
} |
|
|
|
const reader = new FileReader(); |
|
|
|
|
|
reader.onload = function (e2) { |
|
status.textContent = 'Image loaded'; |
|
|
|
imageContainer.innerHTML = ''; |
|
outputContainer.innerHTML = ''; |
|
const image = document.createElement('img'); |
|
image.src = e2.target.result; |
|
imageContainer.appendChild(image); |
|
setTimeout(() => start(image.src), 0) |
|
}; |
|
reader.readAsDataURL(file); |
|
}); |
|
|
|
async function start(source) { |
|
startTime = new Date(); |
|
status.textContent = 'processing'; |
|
console.log('start process') |
|
|
|
const image = await RawImage.read(source); |
|
|
|
const { pixel_values: input } = await processor(image); |
|
|
|
|
|
const { output } = await model({ input }); |
|
console.log('image', RawImage) |
|
|
|
|
|
const matteImage = await RawImage.fromTensor(output[0].mul(255).to('uint8')).resize(image.width, image.height); |
|
|
|
console.log('matteImage', matteImage, output) |
|
|
|
async function renderRawImage(image) { |
|
let rawCanvas = await image.toCanvas(); |
|
const canvas = document.createElement('canvas'); |
|
outputContainer.appendChild(canvas); |
|
canvas.width = image.width; |
|
canvas.height = image.height; |
|
|
|
const ctx = canvas.getContext('2d'); |
|
|
|
ctx.drawImage(rawCanvas, 0, 0); |
|
|
|
} |
|
|
|
|
|
|
|
async function getForeground(rawImage, maskImage) { |
|
const rawCanvas = rawImage.toCanvas(); |
|
const rawCtx = rawCanvas.getContext('2d'); |
|
|
|
const maskCanvas = maskImage.toCanvas(); |
|
const maskCtx = maskCanvas.getContext('2d'); |
|
|
|
const rawImageData = rawCtx.getImageData(0, 0, rawCanvas.width, rawCanvas.height); |
|
const maskImageData = maskCtx.getImageData(0, 0, maskCanvas.width, maskCanvas.height); |
|
|
|
for (let i = 0; i < rawImageData.data.length; i += 4) { |
|
|
|
rawImageData.data[i + 3] = maskImageData.data[i]; |
|
} |
|
|
|
rawCtx.putImageData(rawImageData, 0, 0); |
|
return rawCanvas; |
|
} |
|
|
|
let foregroundCanvas = await getForeground(image, matteImage); |
|
|
|
|
|
console.log('debug', foregroundCanvas); |
|
|
|
foregroundCanvas.convertToBlob() |
|
.then(function (blob) { |
|
|
|
let img = new Image(); |
|
|
|
|
|
img.src = URL.createObjectURL(blob); |
|
|
|
|
|
outputContainer.appendChild(img); |
|
endTime = new Date(); |
|
const diff = (endTime - startTime) / 1000 |
|
setTimeout(() => status.textContent = 'Finish: ' + diff + 's', 0) |
|
}) |
|
.catch(function (error) { |
|
|
|
console.error("Blob creation error: ", error); |
|
}); |
|
} |
|
|