Создание приложения для распознавания лиц с помощью Tensorflow.js

Задумывались ли вы когда-нибудь над тем, что камера вашего смартфона может быстро распознать ваше лицо с помощью специальных квадратиков? Каким образом она распознает лица, и какой принцип лежит в основе этого процесса?

В этой статье мы разберемся в особенностях распознавания лиц и создадим собственное приложение для этой цели.


Что такое распознавание лиц?

Распознавание лиц  —  это компьютерная технология на основе искусственного интеллекта (ИИ), используемая для поиска и идентификации человеческих лиц на цифровых изображениях. Это означает, что система может идентифицировать человеческое лицо, присутствующее на изображении или видео.

Как работает распознавание лиц?

Приложения для обнаружения лиц используют методы и алгоритмы машинного обучения, применяемые с целью распознавания человеческих лиц на больших изображениях. Такие изображения могут содержать множество объектов, не являющихся лицами, например пейзажи, здания и другие части тела человека (ноги, плечи и руки).

Процесс распознавания лица состоит из нескольких этапов. Сначала происходит получение изображения и преобразование его из RGB (красно-зелено-синего) в оттенки серого, так как в оттенках серого легче обнаружить объекты.

Преобразование RGB-изображения в оттенки серого

Следующим шагом является использование алгоритма признаков Хаара, который в системе обнаружения объектов Виолы-Джонса используется для распознавания лиц. Этот алгоритм применяется при определении расположения человеческого лица в кадре или на изображении.

Все человеческие лица обладают некоторыми универсальными свойствами: область глаз темнее, чем участок соседних пикселей, а область носа светлее, чем область глаз. Этот алгоритм также используется для выделения признаков объекта на изображении. Техника определения краев, линий и центра используется для обнаружения глаз, носа, рта и т. д. Все это нужно для выявления существенных признаков объекта на изображении и извлечения этих признаков для распознавания лица человека.

Изображены признаки Хаара, которые используются для обнаружения лиц

На следующем этапе задаются координаты x, y, w и h. Это позволяет создать прямоугольную рамку на изображении, чтобы показать местоположение лица или, другими словами, интересующую нас область. После этого алгоритм будет делать прямоугольную рамку в любом месте, где обнаружит лицо.

Обнаружение лица на изображении

На этом мы заканчиваем теоретическую часть и переходим к созданию собственной версии приложения для распознавания лиц с помощью live-веб-камеры в браузере.

Предоставление доступа к веб-камере

Для начала нужно предоставить доступ к веб-камере в браузере. Прежде всего, создадим базовый файл index.html, в котором доступ к веб-камере будет предоставляться с помощью тега video.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Facial Detection App</title>
</head>
<body>
<h1>Facial Detection</h1>
<video id="video" autoplay></video>
</body>

<script src="script.js"></script>
</html>

Теперь создадим еще один файл под названием script.js, в котором напишем код Javascript и включим его в index.html.

let video = document.getElementById("video");

const accessCamera = () => {
navigator.mediaDevices
.getUserMedia({
audio: false,
video: { width: 500, height: 400 },
})
.then((stream) => {
video.srcObject = stream;
});
};

accessCamera();

Здесь мы обращаемся к элементу тега video и сохраняем его в переменной video. Функция accessCamera вызывает API getUserMedia, и мы указываем размеры видео (здесь установлена ширина 500 px и высота 400 px, но вы можете подобрать размеры по своему желанию).

Функция getUserMedia возвращает промис с объектом MediaStream, который мы присваиваем свойству srcObject элемента видео. Наконец, мы вызываем функцию accessCamera.

Теперь для запуска мы можем либо использовать расширение live server, либо напрямую открыть файл index.html. Браузер запросит разрешение на доступ к камере. Разрешите доступ  —  и вы увидите на экране видеопоток с веб-камеры.

Выполнение распознавания лица

Для выполнения распознавания человеческого лица мы будем использовать модель Blazeface из модели Simple Face Detection на tensorflow.js. Blazeface  —  это легкая модель, используемая для обнаружения лиц на изображениях.

Из Blazeface мы возьмем следующие теги сценария и добавим их в файл index.html:

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"</script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface"></script>

Вернемся в файл script.js, где создадим переменную с именем model, в которую будет загружена модель Blazeface.

let model;

model = blazeface.load();

Теперь создадим функцию detectFaces, которая будет выполнять распознавание лиц и выдавать необходимый результат.

const detectFaces = async () => {
const prediction = await model.estimateFaces(video, false);
};

Поскольку blazeface.load()  —  асинхронная функция, ей требуется некоторое время для загрузки. Но нам нужно вызывать и detectFaces, поэтому, чтобы избежать путаницы, мы сначала дождемся загрузки видеопотока с веб-камеры. После этого мы дождемся загрузки модели, а затем вызовем detectFaces. При загрузке видеопотока будем использовать слушатель событий loadeddata.

Теперь файл script.js должен выглядеть примерно так:

let video = document.getElementById("video");
let model;

const accessCamera = () => {
navigator.mediaDevices
.getUserMedia({
video: { width: 500, height: 400 },
audio: false,
})
.then((stream) => {
video.srcObject = stream;
});
};

const detectFaces = async () => {
const prediction = await model.estimateFaces(video, false);
};

accessCamera();

// Это событие будет выполнено, когда видео загрузится

video.addEventListener("loadeddata", async () => {
model = await blazeface.load();
detectFaces();
});

В прогнозе будут перечислены объекты, каждый из которых соответствует обнаруженному лицу. Внутри этих объектов мы обнаружим левую верхнюю и правую нижнюю координаты, а также шесть ориентиров лица, соответствующих глазам, ушам, носу и рту.

Теперь используем эти координаты для отображения результатов в прямоугольном поле. Сначала нужно выполнить итеративный проход по массиву прогнозов и нарисовать прямоугольник или точки для ориентиров лица. Для этого мы будем использовать HTML canvas, а ширина и высота будут такими же, как у видеопотока. Поскольку отображать содержимое тега video больше не нужно, установим его свойство display на none.

Вот какой будет окончательная версия файла index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Facial Detection App</title>
</head>
<body>
<h1>Facial Detection</h1>
<video id="video" autoplay style="display: none"></video>
<canvas id="canvas" width="500px" height="400px"></canvas>
</body>

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface"></script>
<script src="script.js"></script>
</html>

Далее нам нужно создать переменную для объекта canvas, а также 2D-контекст. После этого нарисуем в canvas текущий видеопоток, а затем прямоугольник для обнаружения лица, что можно сделать с помощью функций drawImage и rect для HTML canvas.

Поскольку функция detectFaces вызывается только один раз, нужно постоянно вызывать ее, чтобы увидеть результат в видео. Мы будем использовать метод setInterval и вызывать функцию каждые 40 миллисекунд, чтобы получить на выходе около 24 кадров в секунду.

Вот окончательный код script.js:

let video = document.getElementById("video");
let model;

// Объявление переменной canvas и настройка контекста

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");

const accessCamera = () => {
navigator.mediaDevices
.getUserMedia({
video: { width: 500, height: 400 },
audio: false,
})
.then((stream) => {
video.srcObject = stream;
});
};

const detectFaces = async () => {
const prediction = await model.estimateFaces(video, false);

// Использование canvas для рисования видео

ctx.drawImage(video, 0, 0, 500, 400);

prediction.forEach((predictions) => {

// Рисование прямоугольника, который будет определять лицо
ctx.beginPath();
ctx.lineWidth = "4";
ctx.strokeStyle = "yellow";
ctx.rect(
predictions.topLeft[0],
predictions.topLeft[1],
predictions.bottomRight[0] - predictions.topLeft[0],
predictions.bottomRight[1] - predictions.topLeft[1]
);
// Последние два аргумента обозначают ширину и высоту,
// но поскольку модели blazeface возвращают только координаты,
// мы должны вычесть их, чтобы получить ширину и высоту
ctx.stroke();
});
};

accessCamera();
video.addEventListener("loadeddata", async () => {
model = await blazeface.load();
// Вызов функции detectFaces каждые 40 миллисекунд
setInterval(detectFaces, 40);
});

Здесь вы найдете live-демо-версию, чтобы посмотреть конечный результат. Первая загрузка может занять несколько секунд.


Заключение

Вот и все, что требуется для создания приложения для распознавания лиц. В статье мы использовали tensorflow.js  —  отличный инструмент для запуска ML-моделей в браузерах и множества других полезных предварительно обученных моделей.

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Shivam Sinha: Building a Facial Detection App with Tensorflow.js

Предыдущая статьяДаешь меньше ошибок в проектах ПО!
Следующая статьяСоздание проекта Django для регистрации и входа/выхода из системы