Вычисление углов и расстояний между точками

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


Работа с координатами точек

В ml5.js часто используются предобученные модели, возвращающие наборы ключевых точек. Примеры включают poseNet для отслеживания поз и faceApi для детекции лицевых особенностей. Каждая точка имеет координаты (x, y) в двумерной плоскости, иногда дополнительно с вероятностью уверенности confidence.

let nose = pose.keypoints[0].position; // nose.x, nose.y
let leftWrist = pose.keypoints[9].position; // leftWrist.x, leftWrist.y

Ключевой момент: координаты точек всегда выражаются в пикселях относительно верхнего левого угла холста (canvas). Для корректных вычислений важно учитывать масштаб изображения.


Вычисление расстояния между точками

Расстояние между двумя точками A(x1, y1) и B(x2, y2) в двумерном пространстве вычисляется по формуле Евклидова расстояния:

[ d = ]

Пример функции на JavaScript с использованием ml5.js:

function getDistance(pointA, pointB) {
  let dx = pointB.x - pointA.x;
  let dy = pointB.y - pointA.y;
  return Math.sqrt(dx * dx + dy * dy);
}

let distance = getDistance(nose, leftWrist);
console.log("Расстояние:", distance);

Совет: для оптимизации можно использовать Math.hypot(dx, dy), что повышает читаемость кода и предотвращает ошибки при больших значениях координат.


Вычисление углов между тремя точками

Для трех точек A, B, C угол в вершине B определяется через векторное представление:

  1. Создаются два вектора: [ = (x_A - x_B, y_A - y_B), = (x_C - x_B, y_C - y_B)]

  2. Вычисляется угол с помощью скалярного произведения: [ = ]

  3. Перевод в градусы: [ = () ]

Пример функции:

function getAngle(A, B, C) {
  let BAx = A.x - B.x;
  let BAy = A.y - B.y;
  let BCx = C.x - B.x;
  let BCy = C.y - B.y;

  let dotProduct = BAx * BCx + BAy * BCy;
  let magnitudeBA = Math.hypot(BAx, BAy);
  let magnitudeBC = Math.hypot(BCx, BCy);

  let cosTheta = dotProduct / (magnitudeBA * magnitudeBC);
  cosTheta = Math.min(1, Math.max(-1, cosTheta)); // защита от ошибок округления

  let angle = Math.acos(cosTheta) * (180 / Math.PI);
  return angle;
}

let elbowAngle = getAngle(leftShoulder, leftElbow, leftWrist);
console.log("Угол локтя:", elbowAngle);

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

  • Использование Math.min и Math.max предотвращает появление NaN при погрешностях вычислений.
  • Для отслеживания движений тела углы локтей, коленей, запястий позволяют анализировать биомеханику и корректировать позу.

Интеграция с poseNet в ml5.js

Для вычисления углов и расстояний между точками удобно подключить poseNet следующим образом:

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

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

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

function modelReady() {
  console.log("poseNet загружен");
}

function draw() {
  image(video, 0, 0, width, height);
  
  if (poses.length > 0) {
    let pose = poses[0].pose;
    let leftElbow = pose.keypoints[7].position;
    let leftShoulder = pose.keypoints[5].position;
    let leftWrist = pose.keypoints[9].position;

    let angle = getAngle(leftShoulder, leftElbow, leftWrist);
    let distance = getDistance(leftShoulder, leftWrist);

    fill(255, 0, 0);
    textSize(16);
    text(`Угол локтя: ${angle.toFixed(1)}°`, 10, 20);
    text(`Расстояние плечо-запястье: ${distance.toFixed(1)}`, 10, 40);
  }
}

Ключевые моменты интеграции:

  • poseNet.on('pose', callback) предоставляет массив всех найденных поз.
  • Каждая поза содержит массив keypoints с координатами.
  • Расчеты выполняются в цикле draw, что обеспечивает обновление данных в реальном времени.

Практические применения

  1. Анализ осанки и спортивных движений: вычисление углов суставов позволяет строить системы корректировки техники.
  2. Игровые интерфейсы: расстояния между точками рук и тела могут служить триггерами для анимации или управления персонажем.
  3. Медицина и физиотерапия: отслеживание диапазона движений суставов с визуальной обратной связью.
  4. Интерактивные арт-инсталляции: движения тела влияют на генерацию графики или музыки.