Не так давно Google выпустил версию 7.8 библиотеки Google Play Services. В числе мажорных нововведений представлен новый Mobile Vision API, состоящий из двух больших компонентов: Barcode API — для сканирования и распознавания различных штрих- и QR-кодов и обновленный Faces API — для поиска и трекинга лиц на картинках. Под катом познакомимся с Faces API, рассмотрим его основные возможности и напишем небольшое приложение.

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



Хотя в сложных случаях возможны сбои алгоритма:


Ошибка первого рода


Ошибка второго рода

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



Но хватит введения, перейдем к практике. Каждую минуту пользователи Инстаграма заливают 216 тысяч фотографий. Ткнув пальцем в небо, предположим, что 40% из них — селфи. Это же 1440 штук в секунду! Попробуем влиться в тренд и сделаем небольшое приложение для автоматизации селфи. Кислые мины мало кому нравятся, поэтому будем снимать только улыбающиеся лица. Внимательный читатель спросит, а в чем же автоматизация? Все просто: чтобы не заставлять пользователей искать на ощупь кнопку спуска, будем автоматически снимать кадр после того, как человек просто подмигнет в камеру.

В качестве основы будем использовать официальные примеры Vision API от Google. Для простоты вопросы отрисовки кадров с камеры опущены. Интересующиеся могут заглянуть в исходники на гитхабе.

Чтобы подключить Faces API в свой проект достаточно указать в gradle-скрипте зависимость:

compile 'com.google.android.gms:play-services-vision:7.8.0'

Для начала делаем экземпляр детектора. Селфи — дело чаще всего сугубо индивидуальное, поэтому будем трекать лицо только одного человека:

FaceDetector detector = new FaceDetector.Builder(context)
                 // Включаем расчет для глаз и улыбки
                .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
                // Только "главное" лицо в кадре 
                .setProminentFaceOnly(true)   
                .setTrackingEnabled(true)
                .build();

Создаем «мозги» нашего детектора — алгоритм обработки. Детектору нужна фабрика, которая будет создавать экземпляр обработчика для каждого найденного лица. С помощью кучи ужимок перед фронтальной камерой телефона эмпирически было определено: более-менее адекватная улыбка на фото имеет значение 0.4 и выше, а подмигивание можно формализовать так: «вероятности того, что глаза открыты, для правого и левого глаза отличаются более чем на 0.6». Что же, реализуем этот алгоритм в нашем обработчике:

private class GraphicFaceTracker extends Tracker<Face> {
    @Override
    public void onUpdate(FaceDetector.Detections<Face> detectionResults, Face face) {        
        boolean isSmiling = face.getIsSmilingProbability() > 0.4;
        if (isSmiling) {
            float leftEye = face.getIsLeftEyeOpenProbability();
            float rightEye = face.getIsRightEyeOpenProbability();
            if (Math.abs(leftEye - rightEye) >= 0.6) {
                takeShot();  // Делаем снимок
            }
        }
    }
}

private class GraphicFaceTrackerFactory implements MultiProcessor.Factory<Face> {
        @Override
        public Tracker<Face> create(Face face) {
            return new GraphicFaceTracker();
        }
    }

Передаем нашему детектору экземпляр фабрики:

        GraphicFaceTrackerFactory trackerFactory = new GraphicFaceTrackerFactory();
        MultiProcessor<Face> processor = new MultiProcessor.Builder<>(trackerFactory).build();
        detector.setProcessor(processor);

Теперь все, что осталось — просто cоздать и запустить запустить поток с камеры. Важно! Не забыть обязательно корректно остановить камеру, когда она нам больше не нужна. Иначе камера так и останется залоченной, и ни одно приложение не получит к ней доступа, пока не перезагрузится телефон.

CameraSource cameraSource = new CameraSource.Builder(context, detector)
                .setFacing(CameraSource.CAMERA_FACING_FRONT)
                .build().start();

Итак. Компилируем. Запускаем. Пробуем на коллегах. Все работает. Правим баги. Пробуем на коллегах. Все работает.



В целом Faces API оставляет приятное впечатления как для разработчика, так и для пользователя. Разработчикам понравится простота и удобство разработки, а пользователям — скорость и качество работы. Ждем в Play Маркете еще больше приложений с функцией распознавания лиц.

Полезные ссылки:
Документация от Google
Исходники приложения

Комментарии (6)


  1. Spail
    16.10.2015 12:32

    Кстати, на последнем фото селфи делает Android-разработчик Рамблера — вот так у нас все круто :)


    1. Metus
      16.10.2015 13:10
      +5

      Что именно круто?
      Интерьер на фото, счастливое выражение лица или сексизм?


      1. Spail
        16.10.2015 13:16
        +2

        Один бородатый мужик в пестрой рубашке прочитал этот комментарий и заплакал


      1. CAJAX
        16.10.2015 15:15
        +1

        Гугл оценил её счастье в 0.99.


    1. namespace
      16.10.2015 19:53
      +1

      И что, нам тебя похвалить?


    1. stepanp
      16.10.2015 20:52
      +2

      который на фоне с ноутбуком?