Разработка сайтов в Старобельске, ЛНР. Распознавание лиц в Интернете с помощью Face-api.js

Веб-браузеры становятся мощнее с каждым днем. Веб-сайты и веб-приложения также усложняются. Операции, для которых несколько десятилетий назад требовался суперкомпьютер, теперь выполняются на смартфоне. Одной из таких вещей является распознавание лиц.

Возможность обнаруживать и анализировать лицо очень полезна, так как позволяет нам добавлять умные функции. Подумайте об автоматическом размытии лиц (например, Google Maps), панорамировании и масштабировании веб-камеры, чтобы сосредоточиться на людях (например, Microsoft Teams), проверке паспорта, добавлении глупых фильтров (например, Instagram и Snapchat) и многом другом. Но прежде чем мы сможем сделать все это, нам сначала нужно найти лицо!

Face-api.js — это библиотека, которая позволяет разработчикам использовать распознавание лиц в своих приложениях, не требуя опыта работы с машинным обучением.

Код для этого руководства доступен на GitHub.

Распознавание лиц с помощью машинного обучения

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

Однако нейронные сети отлично справляются с такими проблемами и могут быть обобщены для учета большинства (если не всех) условий. Мы можем создавать, обучать и использовать нейронные сети в браузере с помощью TensorFlow.js, популярной библиотеки машинного обучения JavaScript. Однако, даже если мы используем готовую, предварительно обученную модель, мы все равно немного углубимся в мельчайшие детали предоставления информации TensorFlow и интерпретации вывода. Если вас интересуют технические детали машинного обучения, ознакомьтесь с «Учебником по машинному обучению с помощью Python «.

Введите face-api.js. Все это реализовано в интуитивно понятном API. Мы можем передать элемент img, canvas, или videoDOM, и библиотека вернет один или несколько результатов. Face-api.js может обнаруживать лица, а также оценивать различные элементы в них, как указано ниже.

Обнаружение лица: получить границы одного или нескольких лиц. Это полезно для определения того, где и насколько велики лица на изображении.

Обнаружение ориентиров лица: получите положение и форму бровей, глаз, носа, рта и губ, а также подбородка. Это можно использовать для определения направления взгляда или для проецирования графики на определенные области, например усы между носом и губами.

Распознавание лиц: определите, кто на картинке.

Обнаружение выражения лица: получите выражение лица. Обратите внимание, что пробег может отличаться для разных культур.

Определение возраста и пола: узнать возраст и пол по лицу. Обратите внимание, что для «гендерной» классификации лицо классифицируется как женское или мужское, что не обязательно раскрывает его пол.

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

Будьте очень внимательны при использовании этой технологии и тщательно тестируйте ее с помощью разнообразной группы тестирования.

Установка

Мы можем установить face-api.js через npm:

npm install face-api.js

Однако, чтобы пропустить настройку инструментов сборки, я включу пакет UMD через unpkg.org:

/* globals faceapi */

import 'https: //unpkg.com/face-api.js@0.22.2/dist/face-api.min.js’;

После этого нам нужно загрузить правильные предварительно обученные модели из репозитория библиотеки. Определите, что мы хотим узнать по лицам, и используйте раздел «Доступные модели», чтобы определить, какие модели требуются. Некоторые функции работают с несколькими моделями. В этом случае мы должны выбирать между пропускной способностью/производительностью и точностью. Сравните размер файла различных доступных моделей и выберите ту, которая, по вашему мнению, лучше всего подходит для вашего проекта.

Не уверены, какие модели вам нужны для вашего использования? Вы можете вернуться к этому шагу позже. Когда мы используем API без загрузки необходимых моделей, будет выдано сообщение об ошибке, указывающее, какую модель ожидает библиотека.

сообщение об ошибке консоли

Теперь мы готовы использовать API face-api.js.

Примеры

Давайте построим что-нибудь!

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

function loadRandomImage () {

const image = new Image () ;

image.crossOrigin = true;

return new Promise ((resolve, reject) => {

image.addEventListener ('error’, (error) => reject (error));

image.addEventListener ('load’, () => resolve (image));

image.src = 'https: //source.unsplash.com/512×512/? face, friends’;

}) ;

}

Обрезка изображения

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

Во-первых, мы должны выбрать и загрузить модель. Чтобы обрезать изображение, нам нужно знать только граничную рамку лица, поэтому обнаружения лица достаточно. Для этого мы можем использовать две модели: модель SSD Mobilenet v1 (чуть менее 6 МБ) и модель Tiny Face Detector (менее 200 КБ). Скажем, точность не нужна, потому что у пользователей также есть возможность обрезать вручную. Кроме того, предположим, что посетители используют эту функцию при медленном интернет-соединении. Поскольку наше внимание сосредоточено на пропускной способности и производительности, мы выберем меньшую модель Tiny Face Detector.

После загрузки модели мы можем загрузить ее:

await faceapi.nets.tinyFaceDetector.loadFromUri ('/models’) ;

Теперь мы можем загрузить изображение и передать его в face-api.js. faceapi.detectAllFacesиспользует модель SSD Mobilenet v1 по умолчанию, поэтому нам придется явно передать new faceapi.TinyFaceDetectorOptions (), чтобы заставить его использовать модель Tiny Face Detector.

const image = await loadRandomImage () ;

const faces = await faceapi.detectAllFaces (image, new faceapi.TinyFaceDetectorOptions ());

Теперь переменная facesсодержит массив результатов. Каждый результат имеет свойство boxи. scoreОценка показывает, насколько нейронная сеть уверена в том, что результатом действительно является лицо. Свойство boxсодержит объект с координатами лица. Мы могли бы выбрать первый результат (или мы могли бы использовать faceapi.detectSingleFace ()), но если пользователь отправит групповое фото, мы хотим увидеть их всех на обрезанном изображении. Для этого мы можем вычислить пользовательскую граничную рамку:

const box = {

// Set boundaries to their inverse infinity, so any number is greater/smaller

bottom: -Infinity,

left: Infinity,

right: -Infinity,

top: Infinity,

// Given the boundaries, we can compute width and height

get height () {

return this.bottom — this.top;

},

get width () {

return this.right — this.left;

},

};

// Update the box boundaries

for (const face of faces) {

box.bottom = Math.max (box.bottom, face.box.bottom) ;

box.left = Math.min (box.left, face.box.left) ;

box.right = Math.max (box.right, face.box.right) ;

box.top = Math.min (box.top, face.box.top) ;

}

Наконец, мы можем создать холст и показать результат:

const canvas = document.createElement ('canvas’) ;

const context = canvas.getContext ('2d’) ;

canvas.height = box.height;

canvas.width = box.width;

context.drawImage (

image,

box.left,

box.top,

box.width,

box.height,

0,

0,

canvas.width,

canvas.height

) ;

Размещение эмодзи

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

Почему бы не немного повеселиться? Мы можем сделать фильтр, который помещает эмодзи рта (👄) на все глаза. Чтобы найти ориентиры для глаз, нам нужна другая модель. На этот раз мы заботимся о точности, поэтому используем модели SSD Mobilenet v1 и 68 Point Face Landmark Detection.

Опять же, нам нужно сначала загрузить модели и изображение:

await faceapi.nets.faceLandmark68Net.loadFromUri ('/models’) ;

await faceapi.nets.ssdMobilenetv1.loadFromUri ('/models’) ;

const image = await loadRandomImage () ;

Чтобы получить ориентиры, мы должны добавить withFaceLandmarks () вызов функции, detectAllFaces () чтобы получить данные ориентиров:

const faces = await faceapi

.detectAllFaces (image)

.withlandmarks () ;

Как и в прошлый раз, facesсодержит список результатов. В дополнение к тому, где находится лицо, каждый результат также содержит необработанный список точек для ориентиров. Чтобы получить правильные ориентиры для каждой функции, нам нужно разрезать список точек. Поскольку количество точек фиксировано, я решил жестко закодировать индексы:

for (const face of faces) {

const features = {

jaw: face.landmarks.positions.slice (0, 17),

eyebrowLeft: face.landmarks.positions.slice (17, 22),

eyebrowRight: face.landmarks.positions.slice (22, 27),

noseBridge: face.landmarks.positions.slice (27, 31),

nose: face.landmarks.positions.slice (31, 36),

eyeLeft: face.landmarks.positions.slice (36, 42),

eyeRight: face.landmarks.positions.slice (42, 48),

lipOuter: face.landmarks.positions.slice (48, 60),

lipInner: face.landmarks.positions.slice (60),

};

//...

}

Теперь мы, наконец, можем немного повеселиться. Вариантов так много, но давайте закроем глаза смайликом рта (👄).

Сначала мы должны определить, где разместить смайлик и насколько большим он должен быть. Для этого напишем вспомогательную функцию, которая создает прямоугольник из произвольного набора точек. На коробке есть вся необходимая информация:

function getBoxFromPoints (points) {

const box = {

bottom: -Infinity,

left: Infinity,

right: -Infinity,

top: Infinity,

get center () {

return {

x: this.left + this.width / 2,

y: this.top + this.height / 2,

};

},

get height () {

return this.bottom — this.top;

},

get width () {

return this.right — this.left;

},

};

for (const point of points) {

box.left = Math.min (box.left, point.x) ;

box.right = Math.max (box.right, point.x) ;

box.bottom = Math.max (box.bottom, point.y) ;

box.top = Math.min (box.top, point.y) ;

}

return box;

}

Теперь мы можем начать рисовать смайлики поверх картинки. Поскольку мы должны сделать это для обоих глаз, мы можем поместить feature.eyeLeftи feature.eyeRightв массив и выполнить итерацию по ним, чтобы выполнить один и тот же код для каждого глаза. Осталось только нарисовать эмодзи на холсте!

for (const eye of [features.eyeLeft, features.eyeRight]) {

const eyeBox = getBoxFromPoints (eye) ;

const fontSize = 6 * eyeBox.height;

context.font = `${fontSize}px/${fontSize}px serif`;

context.textAlign = 'center’;

context.textBaseline = 'bottom’;

context.fillStyle = '#000';

context.fillText ('👄', eyeBox.center.x, eyeBox.center.y + 0.6 * fontSize) ;

}

Обратите внимание, что я использовал магические числа для настройки размера шрифта и точного положения текста. Поскольку смайлики имеют кодировку Unicode, а типографика в Интернете странная (по крайней мере, для меня), я просто корректирую числа, пока они не будут выглядеть правильно. Более надежной альтернативой было бы использование изображения в качестве наложения.

Шесть человек со смайликами рта вместо глаз

Заключение

Face-api.js — отличная библиотека, которая делает обнаружение и распознавание лиц действительно доступными. Знакомство с машинным обучением и нейронными сетями не требуется. Я люблю инструменты, которые позволяют, и это определенно один из них.

По моему опыту, распознавание лиц в Интернете сказывается на производительности. Нам придется выбирать между пропускной способностью и производительностью или точностью. Меньшие модели определенно менее точны и могут упустить лицо из-за некоторых факторов, о которых я упоминал ранее, таких как плохое освещение или когда лица закрыты маской.

Microsoft Azure, Google Cloud и, возможно, другие компании предлагают распознавание лиц в облаке. Поскольку мы избегаем загрузки больших моделей, облачное обнаружение позволяет избежать тяжелых загрузок страниц, имеет тенденцию быть более точным, поскольку оно часто улучшается, и может быть даже быстрее из-за оптимизированного оборудования. Если вам нужна высокая точность, вы можете изучить план, который вам удобен.

Я определенно рекомендую поиграть с face-api.js для хобби-проектов, экспериментов и, возможно, для MVP.

Делитесь нашими материалами с друзьями!

 

 

Заказать разработку сайта