Добро пожаловать, в этой статье мы возьмем предварительно обученную модель TensorFlow.js BlazeFace и используем ее для выполнения обнаружения лиц на живой веб-камере. кормить. Это продемонстрирует ключевые понятия для TensorFlow.js и базового JavaScript. Наслаждаться!
Оглавление:
- Структура папок и файлов
- Начальные константы DOM и проверка веб-камеры
- Загрузка нашей модели и включение веб-камеры
- Составление и отображение наших прогнозов
1. Настройка HTML и файловая структура
Для начала нам нужно создать файл index.html и заполнить его скелетом 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>TensorflowJS</title> </head> <body> </body> </html>
Затем мы можем заполнить некоторые важные теги для нашего HTMLтела. Начиная с нескольких тегов h1 и p для текста, информирующего пользователя. Затем мы создаем раздел для нашей демонстрации и заполняем его текстом и блоком div, содержащим выход с камеры. Он будет содержать как нашу кнопку Включить веб-камеру, так и видео размером 640x480. Обратите внимание, что размер может быть изменен, но модель должна быть соответствующим образом скорректирована.
<h1>Facial Recognition using a TensorflowJS pre trained model</h1> <p>The model may take some time to load, the button will be available to click once it is.</p> <section id="demo" class="invisible"> <p>Keep your face in frame and the model should be able to recognize it and draw a bounding box!</p> <div id="liveView" class="camView"> <button id="webcamButton">Enable Webcam</button> <video id="webcam" autoplay muted width="640" height="480"></video> </div> </section>
Теперь мы можем добавить ссылки на наш CSS, базовый JavaScript, TensorflowJS и модель, которую мы будем использовать, известную как BlazeFace. Эта модель находится в открытом доступе, и вы можете найти информацию о ней, как и о многих других, в профиле TensorFlow на Github. Мы импортируем CSS в заголовок и JavaScript в нижнюю часть тела. Мы также можем добавить наши файлы style.css и index.js, пока мы это делаем.
<!-- Import CSS --> <link rel="stylesheet" href="style.css"> . . . <!-- Page Specific Javascript --> <script src="index.js" defer></script> <!-- Import TensorFlow.js library --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script> <!-- Load the blazeface model to use to recognize things in images --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/blazeface"></script>
На данный момент ваш живой сайт должен выглядеть примерно так: Это функционально, но не очень эстетично, поэтому, возможно, нам придется немного украсить его.
Теперь мы можем настроить простой CSS, чтобы сайт выглядел лучше и чтобы пользователи не нажимали кнопку веб-камеры до загрузки модели. Мы также настраиваем свойства наших классов highlighter и featureIndicator, которые позже будут использоваться для отображения ограничивающей рамки для лица и кругов, представляющих ключевые черты лица.
body { font-family: arial, sans-serif; color: #3D3D3D; } h1 { color: #7711ebee; font-size: 2.5rem; font-weight: bold; } video { display: block; } section { opacity: 1; transition: opacity 500ms ease-in-out; } .removed { display: none; } .invisible { opacity: 0.2; } .camView { position: relative; float: left; width: calc(100% - 20px); margin: 10px; cursor: pointer; } .camView p { position: absolute; padding: 5px; background-color: rgba(76, 0, 255, 0.85); color: #FFF; border: 1px dashed rgba(255, 255, 255, 0.7); z-index: 2; font-size: 12px; } .highlighter { background: rgba(76, 0, 255, 0.2); border: 1px dashed #fff; z-index: 1; position: absolute; } .featureIndicator { background: rgb(255, 174, 0); z-index: 1; position: absolute; border-radius: 50%; }
Теперь ваш сайт должен выглядеть примерно так.
2. Исходные константы DOM и проверка веб-камеры
Теперь, когда у нас есть HTMLскелет и простые стили, мы можем начать структурировать наш JavaScript. Мы будем хранить все наши JS вместе в нашем файле index.js, который ранее был импортирован с помощью тега скрипта. Для начала мы определимнеобходимые константы для подключения к важным элементам в DOM. К ним относятся наше подключение к веб-камере, просмотр в реальном времени, где мы будем отображать наш выходной видеопоток (после запуска модели), наш общий демонстрационный раздел, который в настоящее время «невидим», и нашу кнопку веб-камеры, которую мы нажмем, чтобы включить нашу веб-камеру.
const video = document.getElementById('webcam');
const liveView = document.getElementById('liveView');
const demosSection = document.getElementById('demo');
const enableWebcamButton = document.getElementById('webcamButton');
Далее нам нужно создать функцию, чтобы проверить, поддерживается ли пользовательское мультимедиа (чтобы получить доступ к веб-камере), и добавить прослушиватель событий для нашей кнопки. Обратите внимание: поскольку мы еще не определили функцию enableCam, на этом этапе мы получим ошибку JavaScript.
getUserMediaSupported() { return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia); } if (getUserMediaSupported()) { enableWebcamButton.addEventListener('click', enableCam); } else { console.warn('getUserMedia() is not supported by your browser'); }
3. Загрузка нашей модели и включение веб-камеры
Теперь нам нужно загрузить нашу модель и дождаться завершения этого действия, так как это может занять некоторое время. Как только он будет загружен, мы можем удалить наш невидимый класс для этого раздела. Обратите внимание, что мы по-прежнему не определили enableCam как функцию для нашего предыдущего прослушивателя событий, и поэтому все равно получим ошибку JavaScript.
blazeface.load().then(function (loadedModel) { blazeModel = loadedModel; demosSection.classList.remove('invisible'); });
Затем мы можем включить камеру после того, как модель будет загружена, и настроить исходный объект нашего видео.
function enableCam(event) { if (!blazeModel) { return; } event.target.classList.add('removed'); const constraints = { video: true }; navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { video.srcObject = stream; video.addEventListener('loadeddata', predictWebcam); }); }
4. Создание и отображение наших прогнозов
Когда кнопка включения веб-камеры заработает, мы можем начать делать прогнозы для нашего потока с веб-камеры, используя модель BlazeFace, а затем заполнить видеопоток с несколькими разделами-индикаторами, использующими пару вспомогательных функций. Чтобы делать прогнозы, мы сначала вызываем метод estimateFaces модели. Затем мы обязательно удаляем все старые элементы div, которые могут присутствовать в последнем кадре. После этого нам нужно перебрать наши прогнозы (поскольку может быть несколько лиц), проверить, превышает ли определенность определенный >threshold и извлеките информацию, чтобы создать разделы индикаторов.
function predictWebcam() { const returnTensors = false; blazeModel.estimateFaces(video, returnTensors).then(function (predictions) { for (let i = 0; i < children.length; i++) { liveView.removeChild(children[i]); } children.splice(0); for (let n = 0; n < predictions.length; n++) { if (predictions[n].probability > 0.66) { let predictionsArray = predictions[n]; let boundStart = predictionsArray.topLeft; let boundEnd = predictionsArray.bottomRight; let landmarks = predictionsArray.landmarks; for (let k=0; k < landmarks.length; k++) { createFeatureIndicator(landmarks[k][0], landmarks[k][1]); } createFaceBoundBox(boundStart, boundEnd); } } window.requestAnimationFrame(predictWebcam); }); }
Теперь нам нужно определить вспомогательные функции для createFeatureIndivator и createFaceBoundBox, на которые мы ссылались ранее, чтобы фактически заполнить видео нашими элементами div. Эти вспомогательные функции служат для создания наших элементов DOM и добавления их в наш liveViewdiv. Местоположение и размер этих дочерних элементов берутся из самой модели. Мы также инициализируем переменную blazeModel, чтобы расширить область ее применения.
function createFaceBoundBox(start, end) { let size = [end[0] - start[0], end[1] - start[1]]; const highlighter = document.createElement('div'); highlighter.setAttribute('class', 'highlighter'); highlighter.style = 'left: ' + start[0] + 'px; top: ' + start[1] + 'px; width: ' + size[0] + 'px; height: ' + size[1] + 'px;'; liveView.appendChild(highlighter); children.push(highlighter); } function createFeatureIndicator(x, y) { const featureIndicator = document.createElement('div'); featureIndicator.setAttribute('class', 'featureIndicator'); featureIndicator.style = "left: " + x + "px;" + "top: " + y + "px;" + "width: .5rem; height: .5rem;" liveView.appendChild(featureIndicator); children.push(featureIndicator); } var blazeModel = undefined;
Благодаря этому наша веб-страница теперь полностью функциональна и должна работать и делать прогнозы на основе данных с веб-камеры!
Надеюсь, вам было интересно читать, так как мне очень понравилось писать эту статью. Заботиться!