Пример использования Faces API от Google

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

1cd0746cb310400fa1644a5cf4aabde2.jpg

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

38ffdbee530a4a75ae01737f9e4599cb.jpg

Ошибка первого рода
126275741d3a40d29a59a853b1364d32.jpg

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


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

3d9986d9bf7e44c892e0f5517fad03ed.jpg

Но хватит введения, перейдем к практике. Каждую минуту пользователи Инстаграма заливают 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();


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

a9e7b4a1c1274c858e7d61575c7ef7d5.jpg

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

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

© Habrahabr.ru