Библиотека ml5.js предоставляет высокоуровневый интерфейс для работы с машинным обучением в браузере на языке JavaScript. Одной из возможностей является распознавание жестов рук с использованием модели Handpose, которая позволяет получать точные координаты ключевых точек кисти. Эти данные открывают путь к вычислению жестов на основе геометрии пальцев.
Модель Handpose строится на TensorFlow.js и
возвращает массив из 21 ключевой точки для каждой руки, включающий
суставы пальцев и запястье. Каждая точка имеет координаты
(x, y, z), где x и y — позиция на
экране, а z — глубина относительно камеры. Эти координаты
являются основой для всех дальнейших вычислений и анализа жестов.
Пример загрузки и инициализации модели:
let handposeModel;
let video;
async function setup() {
video = createCapture(VIDEO);
video.size(640, 480);
handposeModel = await ml5.handpose(video, modelReady);
}
function modelReady() {
console.log("Модель Handpose загружена");
handposeModel.on("predict", gotHands);
}
После подключения модели, каждая детекция руки возвращает массив ключевых точек. Для удобства часто создаются структуры данных, где каждому пальцу соответствует набор точек:
Ключевая точка 0 — запястье, она используется как
базовая точка для измерений и расчёта углов.
Для распознавания жестов применяются векторные и угловые вычисления:
Расстояние между двумя точками (x1, y1) и
(x2, y2) вычисляется по формуле Евклидова расстояния:
function distance(p1, p2) {
let dx = p2.x - p1.x;
let dy = p2.y - p1.y;
return Math.sqrt(dx*dx + dy*dy);
}
Расстояния помогают определить, согнут палец или выпрямлен, а также ориентацию кисти.
Для определения изгиба пальца рассчитывается угол между двумя сегментами фаланг:
function angle(p1, p2, p3) {
let v1 = {x: p1.x - p2.x, y: p1.y - p2.y};
let v2 = {x: p3.x - p2.x, y: p3.y - p2.y};
let dot = v1.x * v2.x + v1.y * v2.y;
let mag1 = Math.sqrt(v1.x*v1.x + v1.y*v1.y);
let mag2 = Math.sqrt(v2.x*v2.x + v2.y*v2.y);
return Math.acos(dot / (mag1 * mag2)) * (180 / Math.PI);
}
Углы позволяют классифицировать состояния пальцев: выпрямлен, согнут, согнут в кулак.
Для жестов важна ориентация пальцев относительно кисти. Используется вектор из запястья к кончику пальца:
function directionVector(wrist, fingertip) {
return {x: fingertip.x - wrist.x, y: fingertip.y - wrist.y};
}
Сравнение углов направления пальцев относительно горизонтальной или вертикальной оси позволяет различать «вверх», «в сторону» и другие направления.
На основе вычисленных расстояний, углов и направлений строится правилавая система распознавания жестов. Пример:
Эти правила могут комбинироваться с дополнительными признаками, такими как ориентация ладони, расстояние между пальцами и расположение кистей относительно друг друга.
Для наглядности координаты и состояния пальцев часто визуализируются с помощью p5.js:
function drawHand(predictions) {
for (let hand of predictions) {
for (let point of hand.landmarks) {
ellipse(point[0], point[1], 10, 10);
}
for (let finger of hand.annotations) {
for (let i = 0; i < finger.length - 1; i++) {
line(finger[i][0], finger[i][1], finger[i+1][0], finger[i+1][1]);
}
}
}
}
Визуализация помогает проверять правильность вычислений и корректность классификации жестов.
Для плавной работы в браузере необходимо учитывать следующие моменты:
requestAnimationFrame вместо
setInterval для синхронизации с рендерингомТакой подход обеспечивает стабильное распознавание жестов и минимизирует задержки между движением руки и визуальной обратной связью.
На основе геометрии пальцев создаются:
Комбинация ml5.js, Handpose и вычислений на основе координат суставов обеспечивает гибкий и точный инструмент для анализа жестов на основе геометрии пальцев.