Отрисовка скелета и ключевых точек

Библиотека ml5.js предоставляет удобный интерфейс для работы с моделями машинного обучения в браузере на JavaScript. Одним из наиболее часто используемых инструментов является PoseNet, позволяющий детектировать позы человека и получать координаты ключевых точек тела в реальном времени.


Инициализация PoseNet

Для начала работы необходимо подключить библиотеку ml5.js и создать видео- или canvas-элемент, на котором будет производиться анализ. PoseNet в ml5.js создается следующим образом:

let video;
let poseNet;
let poses = [];

function setup() {
  createCanvas(640, 480);
  video = createCapture(VIDEO);
  video.size(width, height);
  video.hide();

  poseNet = ml5.poseNet(video, modelReady);
  poseNet.on('pose', function(results) {
    poses = results;
  });
}

function modelReady() {
  console.log("PoseNet модель загружена");
}

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

  • createCapture(VIDEO) — захват видео с веб-камеры.
  • poseNet(video, callback) — инициализация модели на видеопотоке.
  • poseNet.on('pose', callback) — подписка на события распознавания поз.

Структура данных ключевых точек

Результатом работы PoseNet является массив объектов poses, каждый из которых содержит информацию о положении человека. Каждый объект имеет структуру:

{
  "pose": {
    "keypoints": [
      {
        "score": 0.99,
        "part": "nose",
        "position": {"x": 123, "y": 456}
      },
      ...
    ]
  }
}

Пояснения:

  • part — название ключевой точки (нос, глаза, плечи, локти, колени, стопы и др.).
  • position — координаты точки в пикселях относительно canvas.
  • score — уверенность модели в корректности детекции точки (0–1).

Отрисовка ключевых точек

Для визуализации ключевых точек удобно использовать функцию ellipse(). Рекомендуется фильтровать точки по score, чтобы отображать только надёжные результаты:

function drawKeypoints() {
  for (let i = 0; i < poses.length; i++) {
    let pose = poses[i].pose;
    for (let j = 0; j < pose.keypoints.length; j++) {
      let keypoint = pose.keypoints[j];
      if (keypoint.score > 0.5) {
        fill(255, 0, 0);
        noStroke();
        ellipse(keypoint.position.x, keypoint.position.y, 10, 10);
      }
    }
  }
}

Рекомендации по визуализации:

  • Использовать разные цвета для разных частей тела при необходимости.
  • Корректировать размер точек в зависимости от масштаба видео.

Отрисовка скелета

Скелет создаётся соединением ключевых точек, определённых моделью. ml5.js предоставляет информацию о связях между точками в массиве skeleton.

function drawSkeleton() {
  for (let i = 0; i < poses.length; i++) {
    let skeleton = poses[i].skeleton;
    for (let j = 0; j < skeleton.length; j++) {
      let partA = skeleton[j][0];
      let partB = skeleton[j][1];
      stroke(0, 255, 0);
      strokeWeight(2);
      line(partA.position.x, partA.position.y, partB.position.x, partB.position.y);
    }
  }
}

Пояснения:

  • Каждый элемент skeleton содержит пару ключевых точек [partA, partB], соединяемых линией.
  • strokeWeight определяет толщину линий, stroke — их цвет.
  • Этот подход позволяет строить динамичный каркас тела в реальном времени.

Объединение ключевых точек и скелета

Для полноценной визуализации полезно объединять функции отрисовки точек и соединений:

function draw() {
  image(video, 0, 0, width, height);
  drawKeypoints();
  drawSkeleton();
}

Особенности работы с видео:

  • Важно использовать video.hide(), чтобы не отображать оригинальный HTML-элемент, а управлять выводом через canvas.
  • Частота обновления изображения напрямую зависит от fps видео и производительности устройства.

Настройка порога детекции

Для повышения точности можно изменять минимальное значение score при отрисовке ключевых точек. Например, для сложных движений лучше выставлять более высокий порог, чтобы исключить ложные детекции:

const confidenceThreshold = 0.6;

if (keypoint.score > confidenceThreshold) {
  ellipse(keypoint.position.x, keypoint.position.y, 10, 10);
}

Это особенно важно при работе с несколькими людьми на кадре или в условиях плохого освещения.


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

  • Использовать уменьшенный размер видео (video.size(320, 240)), если высокая частота кадров критична.
  • Отрисовывать только ключевые части тела по необходимости (например, только руки и ноги для жестового управления).
  • Разделять функции обновления и визуализации для предотвращения лагов интерфейса.

Если потребуется, можно добавить расширенную визуализацию: отображение скорости движения ключевых точек, цветовое кодирование частей тела по интенсивности движения, анимацию соединений и динамическое масштабирование для различных разрешений canvas.