Изменения

Перейти к: навигация, поиск
м
Откат правок 185.220.100.241 (обсуждение) к версии YaroslavSviridov
{{В разработке}}
====Описание====
Задача отслеживания взгляда пользователя является частным случаем более общей задачи [http://neerc.ifmo.ru/wiki/index.php?title=Оценка_положения оценки положения]. Решить подобную задачу не так уж и трудно благодаря JavaScript-библиотеке TensorFlow.js <ref>[https://www.tensorflow.org/js/ TensorFlow.js {{---}} JavaScript библиотека для машинного обучения]</ref>. В браузере очень легко получить доступ к веб-камере. Если предположить, что в качестве входных данных для нейронной сети будет использоваться всё изображение с камеры, то можно сказать, что оно для этих целей слишком велико. Системе придётся проделать большую работу только для того, чтобы определить то место на изображении, где находятся глаза. Такой подход может хорошо показать себя в том случае, если речь идёт о модели, которую разработчик обучает самостоятельно и развёртывает на сервере, однако если мы говорим об обучении и использовании модели в браузере — это уже чересчур.
Для того чтобы облегчить задачу сети, мы можем предоставить ей лишь часть изображения — ту, которая содержит глаза пользователя [[Файл:Eyes.png |400px|thumb| right| Рис. 1 Процесс выделения глаз.]] и небольшую область вокруг них. Эту область, представляющую собой прямоугольник, окружающий глаза, можно выявить с помощью сторонней библиотеки.
Для обнаружения лица на изображении воспользуемся библиотекой, которая называется clmtrackr <ref>[https://github.com/auduno/clmtrackr clmtrackr{{---}} JavaScript библиотека для обнаружения лица]</ref>.
Если в качестве входа для простой свёрточной нейронной сети используется маленькое, но с умом подобранное изображение, сеть, без особых проблем, сможет обучиться.
====Алгоритм====
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');
6.'''Отслеживание перемещений мыши'''
Для того чтобы узнать, где именно на веб-странице расположен указатель мыши, нам понадобится обработчик события <code>document.onmousemove</code>. Функция нормализует координаты таким образом, чтобы они укладывались в диапазон [-1, 1].<tt>
const mouse = {
x: 0,
}
document.onmousemove = mouse.handleMouseMove;
</tt>
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),
}
Также прежде чем приступать к обучению сети, зададим фиксированное количество эпох и переменный размер [http://neerc.ifmo.ru/wiki/index.php?title=Batch-normalization пакета ] (так как мы, возможно, будем работать с очень маленькими наборами данных).
function fitModel() {
const image = getImage();
const prediction = currentModel.predict(image);
// Конвертируем нормализованные координаты в позицию на экране:
const targetWidth = ('#target').outerWidth();
const targetHeight = ('#target').outerHeight();
На выходе мы получили систему слежения за человеческим взглядом, у которой даже есть практическое применение.
Например при исследовании пользовательского опыта, во время проектирования и разработки интерфейсов веб-сайтов применяются тепловые карты.
'''Тепловая карта сайта'''<ref>[https://spyserp.com/ru/blog/heatmap-tool '''Тепловая карта сайта'''] </ref> {{--- }} это инструмент, который использует цветовую палитру для визуализации данных на графике. Например, если вы смотрите на веб-страницу и хотите знать, какие элементы привлекают больше всего внимания, тепловая карта покажет эту информацию на основании пользовательских данных.
Полный код разобранного в этом материале примера можно найти [https://github.com/cpury/lookie-lookie/tree/master/blogcode здесь].
Посмотреть на реализованную полную версию разобранного примера можно [https://cpury.github.io/lookie-lookie/ здесь].
 
== См.также ==
*[[Компьютерное зрение]]
==Примeчания==
<references/>
== Источники информации==
 
* [http://sv-journal.org/2015-4/09/index.php?lang=ru Автоматическая оценка ракурса лица в кадре и приведение изображения к нулевым углам поворота.]
* [https://github.com/cpury/lookie-lookie/tree/master/blogcode Проект по трекингу взгляда]
* [https://habr.com/ru/company/ruvds/blog/426055/ TensorFlow.js и clmtrackr.js: отслеживание направления взгляда]
{{В разработке}}
 
[[Категория:Машинное обучение]]
[[Категория:Компьютерное зрение]]

Навигация