ONNX Runtime Web (ORT Web) предоставляет возможность запускать модели машинного обучения прямо в браузере с использованием JavaScript. Одним из частых сценариев является обработка изображений, будь то классификация, детекция объектов или сегментация. Для эффективной работы с изображениями ключевую роль играет интеграция с Canvas API и OffscreenCanvas, обеспечивающая гибкую подготовку данных для модели.
Canvas API позволяет рисовать изображения на элементе
<canvas> и получать доступ к пиксельным данным через
объект ImageData. Основные этапы работы:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const image = new Image();
image.src = 'image.jpg';
image.onl oad = () => {
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
};
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const { data, width, height } = imageData;
data — это массив байтов в формате RGBA, где каждый
пиксель представлен четырьмя последовательными числами.width и height определяют размер
изображения, необходимый для нормализации и изменения формы данных перед
передачей в модель.Модель ONNX обычно ожидает входной тензор в формате
[N, C, H, W] (batch, channels, height, width) с плавающей
точкой. Для преобразования используется Float32Array:
function preprocessImage(imageData) {
const { data, width, height } = imageData;
const floatData = new Float32Array(width * height * 3); // RGB
for (let i = 0; i < width * height; i++) {
floatData[i * 3] = data[i * 4] / 255.0; // R
floatData[i * 3 + 1] = data[i * 4 + 1] / 255.0; // G
floatData[i * 3 + 2] = data[i * 4 + 2] / 255.0; // B
}
return floatData;
}
[0, 1] или
согласно параметрам модели.OffscreenCanvas позволяет создавать canvas вне DOM и
выполнять обработку изображений в Web Worker, что
ускоряет работу и разгружает основной поток:
const offscreen = new OffscreenCanvas(width, height);
const ctx = offscreen.getContext('2d');
ctx.drawImage(imageBitmap, 0, 0, width, height);
const imageData = ctx.getImageData(0, 0, width, height);
postMessage можно передавать ImageBitmap или
ImageData между Worker и основным потоком.Пример передачи изображения в Web Worker:
// main.js
const worker = new Worker('worker.js');
const imageBitmap = await createImageBitmap(image);
worker.postMessage({ imageBitmap }, [imageBitmap]);
// worker.js
self.onmess age = async (event) => {
const { imageBitmap } = event.data;
const offscreen = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);
const ctx = offscreen.getContext('2d');
ctx.drawImage(imageBitmap, 0, 0);
const imageData = ctx.getImageData(0, 0, offscreen.width, offscreen.height);
const tensorData = preprocessImage(imageData);
// Передача tensorData в ONNX Runtime Web
};
После подготовки тензора его можно передавать в модель ONNX Runtime
Web через ort.InferenceSession:
import * as ort from 'onnxruntime-web';
async function runModel(tensorData, width, height) {
const session = await ort.InferenceSession.create('model.onnx');
const inputTensor = new ort.Tensor('float32', tensorData, [1, 3, height, width]);
const feeds = { input: inputTensor };
const results = await session.run(feeds);
return results.output.data;
}
[1, 3, H, W] соответствует одной
RGB-картинке (batch size = 1).Для моделей с фиксированным размером входа необходимо масштабировать изображение:
ctx.drawImage(image, 0, 0, targetWidth, targetHeight);
const imageData = ctx.getImageData(0, 0, targetWidth, targetHeight);
const tensorData = preprocessImage(imageData);
targetWidth и targetHeight выбираются
согласно архитектуре модели.const mean = [0.485, 0.456, 0.406];
const std = [0.229, 0.224, 0.225];
for (let i = 0; i < floatData.length / 3; i++) {
floatData[i * 3] = (floatData[i * 3] - mean[0]) / std[0];
floatData[i * 3 + 1] = (floatData[i * 3 + 1] - mean[1]) / std[1];
floatData[i * 3 + 2] = (floatData[i * 3 + 2] - mean[2]) / std[2];
}
Кроме масштабирования, OffscreenCanvas позволяет применять различные графические эффекты перед подачей на модель:
ctx.filter.ctx.rotate
и ctx.scale.ctx.drawImage с указанием координат.Такой подход повышает гибкость подготовки данных и снижает нагрузку на основной поток браузера.
Float32Array и правильная
нормализация критичны для корректной работы модели.RGB/BGR)
предотвращает ошибки в инференсе.Использование этих инструментов совместно с ONNX Runtime Web обеспечивает эффективную и гибкую обработку изображений для задач машинного обучения в браузере.