Изменения

Перейти к: навигация, поиск
Нет описания правки
====Алгоритм====
1. '''Подготовка'''. <br/>Загрузка библиотек, подготовка пустого HTML-документа с которым будем работать.
2. '''Получение видеопотока с веб-камеры'''<br/>Запрашиваем разрешение пользователя на активацию веб-камеры. Начинаем получать видео с камеры и создаем функции контроля за потоком.
3. '''Поиск лица'''. <br/> Используем библиотеку clmtrackr.js для поиска лица на видео. Для начала инициализируем систему слежения за лицом.<br/><code>  const ctrack = new clm.tracker();<br/> ctrack.init();</code><br/> Теперь, в функции <code>onStreaming()</code>, подключяем подключаем систему поиска лица, добавляя туда следующую команду:<code>ctrack.start(video);</code>Теперь, каждый раз, когда браузер выводит очередной кадр видео, мы собираемся рисовать что-то на элементе <canvas>. Выполнение какого-либо кода при выводе каждого кадра выполняется с помощью механизма <code>requestAnimationLoop()</code>.Теперь вызовем функцию <code>trackingLoop() </code> в функции <code>onStreaming() </code> сразу после <code>ctrack.start()</code>. Эта функция будет сама планировать собственный перезапуск в каждом кадре.<br/><tt>
const overlay = $('#overlay')[0];
const overlayCC = overlay.getContext('2d');
function trackingLoop() {
// Проверим, обнаружено ли в видеопотоке лицо, // и если это так - , то начнём его отслеживать.
requestAnimationFrame(trackingLoop);
let currentPosition = ctrack.getCurrentPosition();
}
}
</tt>4. '''Выявление области изображения, содержащей глаза'''.
[[Файл:Face.png |250px|thumb|right| Рис. 2 Контрольные точки.]]Решим, что глаза — это прямоугольная часть изображения, границы которой касаются точек 23, 28, 24 и 26, расширенная на 5 пикселей в каждом направлении. Этот прямоугольник должен включать в себя всё, что для нас важно, если только пользователь не слишком сильно наклоняет голову.
Следующая функция вернёт координаты ''x '' и ''y'', а также ширину и высоту прямоугольника, окружающего глаза. Она, в качестве входных данных, принимает массив positions, полученный от clmtrackr. Обратите внимание на то, что каждая координата, полученная от clmtrackr, имеет компоненты ''x '' и ''y''.
function getEyesRectangle(positions) {
const minX = positions[23][0] - 5;
if (currentPosition) {
// Выведем линии, проведённые между контрольными точками
// на элементе <canvas>, наложенном на элемент <video>.
ctrack.draw(overlay);
// Получим прямоугольник, ограничивающий глаза, и обведём его
// красными линиями.
const eyesRect = getEyesRectangle(currentPosition);
overlayCC.strokeStyle = 'red';
// Видеопоток может иметь особые внутренние параметры,
// поэтому нам нужны эти константы для перемасштабирования
// прямоугольника с глазами перед обрезкой.
const resizeFactorX = video.videoWidth / video.width;
const resizeFactorY = video.videoHeight / video.height;
// Вырезаем прямоугольник с глазами из видео и выводим его
// в соответствующем элементе <canvas>.
const eyesCanvas = $('#eyes')[0];
const eyesCC = eyesCanvas.getContext('2d');
7. '''Захват изображения'''
Для захвата изображения, выводимого элементом <canvas> и сохранения его в виде тензора, TensorFlow.js предлагает вспомогательную функцию <code>tf.fromPixels()</code>. Используем её для сохранения и последующей нормализации изображения.
function getImage() {
// Захват текущего изображения в виде тензора.
return tf.tidy(function() {
const image = tf.fromPixels($('#eyes')[0]);
}
function captureExample() {
// Возьмём самое свежее изображение глаз и добавим его в набор данных:
tf.tidy(function() {
const image = getImage();
const mousePos = tf.tensor1d([mouse.x, mouse.y]).expandDims(0);
// Решим, в какую выборку (обучающую или контрольную) его добавлять:
const subset = dataset[Math.random() > 0.2 ? 'train' : 'val'];
if (subset.x == null) {
// Создадим новые тензоры:
subset.x = tf.keep(image);
subset.y = tf.keep(mousePos);
} else {
// Конкатенируем их с существующими тензорами:
const oldX = subset.x;
const oldY = subset.y;
subset.y = tf.keep(oldY.concat(mousePos, 0));
}
// Увеличим счётчик:
subset.n += 1;
});
Привяжем данную функцию к какой-нибудь клавише, например <tt>пробел</tt>.
$('body').keyup(function(event) {
// Выполняется при нажатии на клавишу Пробел на клавиатуре.
if (event.keyCode == 32) {
captureExample();
8. '''Обучение модели'''
Создадим простую [https://ru.wikipedia.org/wiki/Свёрточная_нейронная_сеть свёрточную нейронную сеть]. TensorFlow.js предоставляет для этой цели API, напоминающее Keras. У сети есть слой ''conv2d'', слой ''maxPooling2d'', и слой ''dense '' c двумя выходными значениями (они представляют экранные координаты), в качестве регуляризатора, слой ''dropout'', и слой ''flatten '' для того, чтобы преобразовать двухмерные данные в одномерные. Обучение сети выполняется с помощью оптимизатора ''Adam''.
let currentModel;
function createModel() {
model.add(tf.layers.flatten());
model.add(tf.layers.dropout(0.2));
// Два выходных значения x и y.
model.add(tf.layers.dense({
units: 2,
activation: 'tanh',
}));
// Используем оптимизатор Adam с коэффициентом скорости обучения 0.0005 и с функцией потерь MSE:
model.compile({
optimizer: tf.train.adam(0.0005),
const image = getImage();
const prediction = currentModel.predict(image);
// Конвертируем нормализованные координаты в позицию на экране:
const targetWidth = ('#target').outerWidth();
const targetHeight = ('#target').outerHeight();
{{В разработке}}
 
[[Категория:Машинное обучение]]
[[Категория:Компьютерное зрение]]
15
правок

Навигация