Пишемо веб-аплікацію для розпізнавання людей за годину


Дізнайтесь більше про нові кар'єрні можливості в EchoUA. Цікаві проекти, ринкова оплата, гарний колектив. Надсилайте резюме та приєднуйтеся до нас.

Розповідає Деван Сабаратнам, розробник із 30-річним стажем


У вихідні, гортаючи Amazon Web Services, я помітив новий сервіс “Rekognition”. Припустив, що це друкарська помилка (recognition – англ. розпізнавання), але вона привернула мою увагу. Я зацікавився: що це за сервіс? Amazon звик додавати нові сервіси до своєї платформи з регулярністю, що лякала, і цей пройшов повз мене. 

Я дізнався, що наприкінці 2016 року Amazon випустила власний сервіс для розпізнавання зображень на базі глибокого навчання на їх платформі. Він може розпізнавати не лише обличчя, але й об’єкти на фото. Оскільки сервіс новий, подробиць про нього було небагато, але мені захотілося негайно випробувати його. Загалом, протягом години я написав приклад веб-сторінки, яка може отримувати фотографії з моєї веб-камери і виконувати елементарне розпізнавання обличчя на ньому.

Прим. перекл. Щоб не загубитися на численних сервісах Amazon, радимо Вам прочитати нашу шпаргалку з AWS.

Раніше я займався технологією розпізнавання облич, використовуючи сторонні бібліотеки, а також Microsoft Face API, але всі спроби створення подібного додатка не увінчалися успіхом. Переглядаючи документацію “Rekognition”, я зрозумів, що AWS API насправді дуже простий у використанні, тому негайно взявся до роботи.

Мета

Мені була потрібна проста веб-сторінка, яка дозволила б робити фотографію за допомогою камери мого iMac і виконувати розпізнавання на фотографії. Зокрема, я хотів би визначати користувача, що сидить перед комп’ютером.

Сервіс Amazon Rekognition дозволяє створювати одну або декілька колекцій. Колекція – це набір лицьових векторів для фотографій, які Ви хочете зберегти.

Примітка: Сервіс зберігає не фотографії, а їх JSON-представлення.

Після створення колекції Ви можете сфотографувати предмет, порівняти його властивості зі збереженими і повернути найближчу відповідність. Звучить просто, чи не так? Щоправда розробка фронтенда веб-сторінки для отримання даних з камери тривала довше, ніж написання бекенда для розпізнавання.

Загалом, веб-сторінка дозволяє створювати або видаляти колекцію лицьових даних на Amazon, завантажувати нові дані, отримані з фотографії, у свою колекцію і порівнювати нові фотографії з наявною колекцією, щоб знайти збіг. Як додаткову фічу я додав у це демо службу Amazon Polly, щоб після розпізнавання фотографії сторінка вітала користувача.

Фронтенд

Я не знав, яку бібліотеку використати для захоплення зображення за допомогою камери iMac. У результаті знайшов на GitHub бібліотеку JPEG Camera, яка дозволяє використати HTML5 Canvas або Flash для зйомки фото. Я вирішив використати її і налаштував під себе написаний на JavaScript зразок.

Бекенд

Для бекенда я використав Ruby-бібліотеку Sinatra, яка може виконувати всю важку роботу за допомогою AWS. Я часто використав Sinatra (насправді Padrino) у своїх проектах і настійно рекомендую цю платформу.

Примітка: Amazon Rekognition пропонує спочатку завантажувати початкові фотографії, які використовує його API, в Amazon S3, а потім обробляти їх. Я хотів уникнути цього непотрібного кроку і замість цього відправляти зображення безпосередньо в API, що мені у результаті вдалося зробити.

Я зумів зробити те саме з їх вітанням Polly. Замість того, щоб зберегти аудіо в MP3-файлі й програвати його, у мене вийшло закодувати дані MP3 безпосередньо в тег

Код

Я розмістив увесь код цього проекту на моїй сторінці на GitHub. Не соромтеся використати і змінювати його. Нижче я постараюся пояснити код детальніше.

Пишемо додаток

Передусім, вам знадобиться обліковий запис Amazon AWS. Я не вдаватимуся до подробиць, оскільки це нескладно, а у разі утруднень можна легко знайти інформацію в Інтернеті.

Створення користувача AWS IAM

Як тільки ви створили обліковий запис AWS, перше, що нам треба зробити, - створити користувача Amazon IAM (Identity & Access Management), який має права на використання служби Rekognition. Ми також задамо права для Amazon Polly.

У консолі Amazon натисніть на кнопку " Сервіси" у верхньому лівому кутку, потім виберіть " IAM". У меню ліворуч виберіть " Користувачі". Ви повинні побачити список існуючих користувачів IAM, яких ви створили в консолі, якщо ви робили це у минулому.

Натисніть кнопку "Додати користувача", розташовану у верхній частині списку, щоб додати нового користувача IAM.

Дайте користувачеві ім'я і переконаєтеся, що ви відмітили пункт "Programmatic Access", оскільки ви використовуватимете цей IAM у виклику API.

Далі приведені налаштування дозволів. Переконайтеся, що ви клацаєте по третьому квадратику на екрані з написом "Attach existing policies directly". Потім в полі пошуку "Filter: Policy Type" введіть " rekognition". Виберіть " AmazonRekognitionFullAccess" зі списку, поставивши поряд з ним галочку.

Потім зміните фільтр пошуку на " polly" і помістите галочку поряд з " AmazonPollyFullAccess".

Тепер у цього IAM права, достатні для Amazon Rekognition і Amazon Polly. Натисніть "Next: Review" в правому нижньому кутку.

На сторінці перегляду ви повинні побачити 2 політику використання, що дають вам повний доступ до Rekognition і Polly. Якщо ви їх не бачите, поверніться і повторіть попередній крок. Потім натисніть кнопку "Створити користувача" в правому нижньому кутку.

Ця сторінка важлива. Запишіть ключі AWS Key і AWS Secret, які ви вказали на цій сторінці, оскільки нам необхідно включити їх в наше застосування нижче.

Це єдиний раз, коли вам будуть показані ці ключі, тому збережете їх і файл CSV з цієї сторінки в надійному місці.

Завантаження коду

Тепер завантажите приклад коду з моєї сторінки GitHub, щоб ви могли змінити його в міру необхідності. Завантажте код у вигляді ZIP- файлу, або склонируйте його у вашу робочу теку.

Перше, що вам треба зробити, - це створити файл з ім'ям .env у робочій теці і ввести ці два рядки, замінивши в них ключі Amazon IAM на свої:

export AWS_KEY=A1B2C3D4E5J6K7L10export AWS_SECRET=T/9rt344ur+ln89we3552H5uKp901

Тепер, якщо у вас встановлений Ruby (не Ruby on Rails), то для установки залежностей запустите команду:

bundle install

Для запуску додатка введіть цю команду:

ruby faceapp.rb

Вона повинна запустити веб-браузер на порту 4567, щоб ви могли побачити веб-сторінку і почати тестування:

http://localhost:4567

Використання додатка

Сама веб-сторінка досить проста. Ви повинні побачити потокове зображення у верхній частині екрану, яке є каналом з вашої веб-камери.

Спершу створіть колекцію, клацнувши по посиланню в самому нижньому лівому кутку сторінки. Це створить порожню колекцію на серверах Amazon для зберігання ваших зображень. Зверніть увагу: ім'я за умовчанням для цієї колекції - faceapp_test, але ви можете змінити його в коді faceapp.rb (рядок 17).

Для того, щоб почати додавання осіб у свою колекцію, попросите декілька людей сісти перед вашим комп'ютером або телефоном і переконатися, що їх обличчя знаходиться тільки в рамці для фотографій (декілька осіб зроблять сканування невдалим). Коли все буде готово, введіть їх ім'я в текстове поле і натисніть кнопку "Додати в колекцію". Повинне з'явитися повідомлення про те, що дані про особу були додані у базу даних.

Після того, як ви створили декілька осіб у своїй базі даних, ви можете попросити випадкову людину сісти перед камерою і натиснути "Порівняти зображення". Якщо ця людина вже додана в колекцію, на екрані повинне з'явитися його ім'я.

Зверніть увагу, що звичайний спосіб роботи Amazon Rekognition полягає в тому, щоб завантажувати фотографію в Amazon S3 Bucket, а потім обробляти його звідти, але я хотів обійти цей крок і фактично відправити ці фотографії безпосередньо до Rekognition як потік байтів, закодований в Base64. На щастя, aws - sdk для Ruby дозволяє використати обидва методи.

Розбір коду

Передусім, давайте поглянемо на HTML- сторінку:

  Face Recognition Test  	 	
  



Face Recognition Test

Your browser does not support a camera!
 
%MINIFYHTML7a64007f812eec1274539cfc0ac6c27c2%

 

 

Create Collection | Delete Collection

Структура сторінки проста: всього декілька блоків, кнопок і посилань. Зверніть увагу на те, що ми використовуємо jQuery, а також Moment.js для вітання, що налаштовується. Код faceapp.js виконує всі складні завдання і надає посилання на бібліотеку камер JPEG.

Ви також можете помітити теги

$(document).ready (function (){ if (window.JpegCamera){ var camera; // Додати фотографії до поточної колекції Rekognition для подальшого порівняння var add_to_collection = function (){ var photo_id = $("#photo_id").val (); if (!photo_id.length){ $("#upload_status").html ("Please provide name for the upload"); return; } var snapshot = camera.capture (); var api_url = "/upload/" + photo_id; $("#loading_img").show (); snapshot.upload ({api _url: api_url}).done (function (response){ $("#upload_result").html (response); $("#loading_img").hide (); this.discard ();
}).fail (function (status_code, error_message, response) { $("#upload_status").html ("Upload failed with status " + status_code + "  (" + error_message + ")"); $("#upload_result").html (response); $("#loading_img").hide (); }); }; // Порівняти фотографію з поточною колекцією Rekognition var compare_image = function () { var snapshot = camera.capture (); var api_url = "/compare"; $("#loading_img").show (); snapshot.upload ({api _url: api_url}).done (function (response){ var data = JSON.parse (response); if (data.id !== undefined){ $("#upload_result").html (data.message + ": " + data.id + ", Confidence: " + data.confidence); // створення звукового звіту $.post ("/speech", {tosay: "Good " + greetingTime (moment ()) + " " + data.id}, function (response){
$("#audio_speech").attr ("src", "data:audio/mpeg;base64," + response); $("#audio_speech")[0].play (); }); } else { $("#upload_result").html (data.message); } $("#loading_img").hide (); this.discard (); }).fail (function (status_code, error_message, response) { $("#upload_status").html ("Upload failed with status " + status_code + "  (" + error_message + ")"); $("#upload_result").html (response); $("#loading_img").hide (); }); }; var greetingTime = function (moment) { var greet = null; if (!moment ||!moment.isValid()) { return; } // Якщо ми не можемо знайти дійсний момент, ми повертаємо порожнє значення var split_afternoon = 12 // Визначення дня var split_evening = 17 // Визначення вечора var currentHour = parseFloat (moment.format ("HH"));
if (currentHour >= split_afternoon && currentHour <= split_evening) { greet = " afternoon"; } else if (currentHour >= split_evening) { greet = " evening"; } else { greet = " morning"; } return greet; } // Визначення кнопок $ ("#add_to_collection").click (add_to_collection); $("#compare_image").click (compare_image); // Ініціалізація виджета камери на екрані var options ={ shutter_ogg _url: "js/jpeg_camera/shutter.ogg", shutter_mp3 _url: "js/jpeg_camera/shutter.mp3", swf _url: "js/jpeg_camera/jpeg_camera.swf" } camera = new JpegCamera ("#camera", options).ready (function (info) { $("#loading_img").hide (); }); }});

Це настроює бібліотеку JPEG Camera, щоб відображати канал на екрані і обробляти завантаження зображень.

Функція add_to_collection () захоплює зображення з камери, а потім виконує запис в кінцеву точку /upload разом з ім'ям користувача в якості параметра. Функція перевіряє, чи дійсно ви ввели ім'я, яке треба в якості унікального ідентифікатора цих даних.

Функція завантаження перевіряє виклик і виводить повідомлення про успішне завершення або помилку.

Функція compare_image () викликається, коли ви натискаєте кнопку "Порівняти зображення". Вона захоплює кадр з камери і передає POST- дані в /compare. Ця кінцева точка поверне або помилку, або структуру JSON, що містить id (ім'я) знайденої особи, а також відсоток схожості.

Якщо особа співпаде з даними з колекції, функція відправить ім'я знайденої особи до /speech. Ця кінцева точка викликає службу Amazon Polly, щоб перетворити вітання у файл MP3, який можна відтворити користувачеві.

Служба Amazon Polly повертає вітання у вигляді бінарного потоку MP3, тому ми беремо цей потік введення-виведення, шифруємо його у форматі Base64 і поміщаємо в якості закодованого початкового посилання в теги

на нашій веб-сторінці. Потім ми можемо викликати .play () для відтворення MP3 через динаміки користувача за допомогою HTML5 Web Audio API.

Прим. перекл. Ви можете дізнатися про Web Audio більше, прочитавши нашу серію статей за цією темою.

Нарешті, у JS-файлі додатка є функція greetingTime (). Вона вирішує, чи потрібно говорити “добрий ранок / день / вечір” залежно від часу доби користувача.

Тепер подивимось на код Ruby:

# faceapp.rbrequire 'rubygems'require 'bundler'Bundler.requirerequire 'sinatra'Dotenv.load# Налаштування перевірки достовірності aws в цьому приложенииAws.config.update ({ :region => 'us - east - 1', :credentials => Aws::Credentials.new(ENV['AWS_KEY'],ENV['AWS_SECRET']) }) # Назва колекції по умолчаниюFACE_COLLECTION = "faceapp_test"# Путьget '/' do # Показати на головній сторінці erb :faceappendpost '/upload/:photoid' do client = Aws::Rekognition::Client.new() response = client.index_faces ({ collection _id: FACE_COLLECTION, external_image _id: params[:photoid], image: {
bytes: request.body.read.to_s } }) "Image uploaded safely"!endpost '/compare' do content_type :json client = Aws::Rekognition::Client.new() response = client.search_faces_by_image ({ collection _id: FACE_COLLECTION, max _faces: 1, face_match _threshold: 95, image: { bytes: request.body.read.to_s } }) if response.face_matches.count > 1 {:message => "Too many faces found"}.to_json elsif response.face_matches.count == 0 {:message => "No face detected"!}.to_json else # "Порівняння закінчив - виявив #{ response.face_matches[0].face.external_image_id } with #{ response.face_matches[0].face.confidence } accuracy". {:id => response.face_matches[0].face.external_image_id, :confidence => response.face_matches[0].face.confidence, :message => "Face found"!}.to_json endendpost '/speech' do client = Aws::Polly::Client.new()
response = client.synthesize_speech ({ output _format: "mp3", voice _id: " Joanna", text: params[:tosay] }) Base64.encode64 (response.audio_stream.string) endget '/collection/:action' do client = Aws::Rekognition::Client.new() collections = client.list_collections ({}).collection_ids case params[:action] when 'create' if !(collections.include? FACE_COLLECTION) response = client.create_collection ({ collection _id: FACE_COLLECTION }) end when 'delete' if(collections.include? FACE_COLLECTION) response = client.delete_collection ({ collection _id: FACE_COLLECTION }) end end redirect '/'end

Тут заданий блок налаштування конфігурації аутентифікації AWS та імені колекції за умовчанням, яке ми використовуватимемо (Ви можете його вільно міняти).

Інша частина коду – це кінцеві точки, які Sinatra слухатиме. Він прослуховує GET в /, щоб відобразити фактичну веб-сторінку кінцевому користувачеві, а також слухає виклики POST до /upload, /compare і /speech, яким JS-файл відправляє дані. Тільки 3-4 рядки коду для кожної з цих кінцевих точок фактично виконують завдання розпізнавання обличчя і мовлення. Детальніше про них можна дізнатися з документації AWS SDK.

Переклад статті “Building a face recognition web app in under an hour”

 

Київ, Харків, Одеса, Дніпро, Запоріжжя, Кривий Ріг, Вінниця, Херсон, Черкаси, Житомир, Хмельницький, Чернівці, Рівне, Івано-Франківськ, Кременчук, Тернопіль, Луцьк, Ужгород, Кам'янець-Подільський, Стрий - за статистикою саме з цих міст програмісти найбільше переїжджають працювати до Львова. А Ви розглядаєте relocate?


Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *