Совместная работа с vanilla JavaScript и другими фреймворками

ml5.js — это высокоуровневая библиотека для машинного обучения в браузере, построенная поверх TensorFlow.js. Она упрощает интеграцию моделей машинного обучения в веб-приложения, предоставляя готовые функции для классификации изображений, распознавания объектов, генерации текста и работы с аудио. При этом она полностью совместима с обычным JavaScript и любыми популярными фронтенд-фреймворками, такими как React, Vue или Angular.


Инициализация ml5.js в проекте

ml5.js можно подключить несколькими способами:

  1. Через CDN:
<script src="https://cdn.jsdelivr.net/npm/ml5@latest/dist/ml5.min.js"></script>
  1. Через npm:
npm install ml5
import * as ml5 from 'ml5';

После подключения библиотека готова к использованию с любым стандартным JavaScript-кодом или модульной системой.


Интеграция с vanilla JavaScript

Работа с классификатором изображений

const classifier = ml5.imageClassifier('MobileNet', () => {
    console.log('Модель загружена');
});

const image = document.getElementById('myImage');

classifier.classify(image, (err, results) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log(results);
});

Особенности:

  • Асинхронная загрузка: ml5.js загружает модели в фоне, поэтому любые операции с ними нужно выполнять в колбэках или промисах.
  • Объекты DOM: Методы библиотеки напрямую принимают HTML-элементы (<img>, <video>, <canvas>), что упрощает интеграцию в существующие страницы.

Работа с веб-камерой

const video = document.getElementById('videoElement');
navigator.mediaDevices.getUserMedia({ video: true })
    .then(stream => {
        video.srcObject = stream;
        video.play();
    });

const poseNet = ml5.poseNet(video, () => {
    console.log('PoseNet готов');
});

poseNet.on('pose', (results) => {
    console.log(results);
});

Ключевые моменты:

  • Видео-стримы можно передавать напрямую в ml5.js без промежуточной обработки.
  • События on('pose', callback) позволяют подписываться на данные модели в реальном времени.

Использование ml5.js с React

React управляет DOM через виртуальное дерево компонентов, поэтому для интеграции ml5.js лучше использовать рефы.

import React, { useRef, useEffect, useState } from 'react';
import * as ml5 from 'ml5';

function ImageClassifier() {
    const imageRef = useRef(null);
    const [results, setResults] = useState([]);

    useEffect(() => {
        const classifier = ml5.imageClassifier('MobileNet', () => {
            if (imageRef.current) {
                classifier.classify(imageRef.current, (err, res) => {
                    if (!err) setResults(res);
                });
            }
        });
    }, []);

    return (
        <div>
            <img ref={imageRef} src="/example.jpg" alt="Example" />
            <ul>
                {results.map((r, i) => <li key={i}>{r.label}: {r.confidence.toFixed(2)}</li>)}
            </ul>
        </div>
    );
}

Особенности интеграции:

  • Использование useRef позволяет передавать DOM-элементы в ml5.js без конфликтов с виртуальным DOM.
  • Асинхронная работа с моделью не блокирует рендер компонента.

Использование ml5.js с Vue

В Vue основной подход аналогичен React, но используется реактивность и ref из Vue.

<template>
  <div>
    <img ref="myImage" src="/example.jpg" />
    <ul>
      <li v-for="(result, index) in results" :key="index">
        {{ result.label }}: {{ result.confidence.toFixed(2) }}
      </li>
    </ul>
  </div>
</template>

<script>
import * as ml5 from 'ml5';
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const myImage = ref(null);
    const results = ref([]);

    onMounted(() => {
      const classifier = ml5.imageClassifier('MobileNet', () => {
        classifier.classify(myImage.value, (err, res) => {
          if (!err) results.value = res;
        });
      });
    });

    return { myImage, results };
  }
}
</script>

Примечания:

  • Vue предоставляет реактивные данные, которые автоматически обновляют интерфейс при изменении результатов.
  • Работа с DOM-элементами через ref позволяет избежать конфликтов с виртуальным деревом.

Асинхронность и промисы

Хотя ml5.js поддерживает колбэки, современные проекты чаще используют промисы или async/await для чистоты кода.

async function classifyImage(imageElement) {
    const classifier = await ml5.imageClassifier('MobileNet');
    const results = await classifier.classify(imageElement);
    console.log(results);
}

const image = document.getElementById('myImage');
classifyImage(image);

Преимущества:

  • Упрощение цепочек вызовов и логики обработки ошибок.
  • Совместимость с современными фреймворками, где колбэки могут усложнять управление состоянием.

Сочетание ml5.js с другими библиотеками

ml5.js можно комбинировать с визуализационными библиотеками (D3.js, p5.js) для создания интерактивных приложений:

const poseNet = ml5.poseNet(video);

poseNet.on('pose', (poses) => {
    poses.forEach(pose => {
        pose.keypoints.forEach(point => {
            ellipse(point.position.x, point.position.y, 10, 10); // p5.js
        });
    });
});

Особенности:

  • ml5.js генерирует данные, а визуализация осуществляется через сторонние библиотеки.
  • Подходит для интерактивных инсталляций и обучающих проектов.

Оптимизация производительности

  1. Загрузка модели один раз: Не создавать классификатор или модель при каждом событии.
  2. Использование canvas для видео: При работе с PoseNet или BodyPix можно предварительно рисовать видео на <canvas>, чтобы уменьшить нагрузку на DOM.
  3. Тайминг обработки: Для реального времени можно пропускать кадры (requestAnimationFrame), чтобы не перегружать CPU.

ml5.js предоставляет простой и понятный интерфейс для интеграции машинного обучения в веб-приложения, при этом оставаясь полностью совместимой с vanilla JavaScript и популярными фронтенд-фреймворками. Правильное использование асинхронности, DOM-рефов и реактивных данных позволяет создавать масштабируемые и интерактивные приложения с минимальными усилиями.