Детекция лиц
Обзор
Процесс детекции лиц в Face SDK состоит из нескольких этапов: детекции лиц, определения антропометрических точек и вычисления углов поворота головы.
Детекция лиц
Детекция лиц в Face SDK выполняется с помощью набора детекторов. Детектор - это алгоритм библиотеки libfacerec, который использует нейронные сети для обнаружения лиц на изображениях и в видеопотоках. Результатом работы детектора являются координаты ограничивающего прямоугольника (bbox) вокруг задетектированного лица.
После того как детектор обнаружил лицо, для оптимизации дальнейшей работы выполняется автоматическая обрезка изображения по вычисленным координатам ограничивающего прямоугольника (bbox). Определение антропометрических точек и вычисление углов поворота головы выполняются уже на обрезанном изображении (кропе лица).
Детекторы
На данный момент доступны следующие детекторы:
- LBF – устаревший детектор, не рекомендован к использованию;
- BLF – детектор, обеспечивающий более высокое качество и скорость детекции, чем LBF, для лиц среднего размера и больше (в том числе в масках). На Android доступно использование GPU ускорения (включено по умолчанию);
- REFA – детектор, более медленный в сравнении с детекторами LBF и BLF, но при этом демонстрирует высокое качество детекции лиц различных размеров (в том числе в масках). Рекомендован для использования в экспертных системах;
- ULD – новый детектор, более быстрый в сравнении с REFA. Позволяет детектировать лица различных размеров (в том числе в масках).
Ниже представлены примеры работы детекторов в различных условиях. Настроить пороги детекции (score_threshold), минимальный размер детектируемого лица (min_size) и другие параметры можно в файлах конфигурации объекта Capturer в папке conf дистрибутива Face SDK (Подробнее в разделе Параметры файлов конфигурации объекта Capturer).
Нажмите, чтобы развернуть таблицу
Нажмите, чтобы развернуть таблицу
Определение антропометрических точек
Для определения антропометрических точек (Face Landmarks) в Face SDK используются фиттеры. Фиттеры - это специальные алгоритмы библиотеки libfacerec, результатом работы которых является набор антрометрических точек с 2D/3D координатами, привязанными к задетектированному лицу. Существует несколько вариантов фиттеров, отличающихся набором антопометрических точек, о которых написано ниже.
Антропометрические точки
Примечание: Узнать, как отобразить антропометрические точки и углы поворота головы, можно в нашем туториале.
Существует четыре набора антропометрических точек: esr, singlelbf, doublelbf, fda, mesh.
- Набор esr – первый созданный и единственный набор, доступный в предыдущих версиях SDK. Набор esr содержит 47 точек;
- Наборы singlelbf и doublelbf обеспечивают большую точность чем esr. Набор singlelbf содержит 31 точку. Набор doublelbf содержит 101 точку. Фактически, этот набор представляет собой два сконкатенированных набора – последние 31 точки набора doublelbf дублируют набор singlelbf (в том же порядке);
- Набор fda обеспечивает более высокое качество в широком диапазоне ракурсов (вплоть до профильных), в отличие от предыдущих наборов, поэтому мы рекомендуем использовать детекторы именно с этим набором. При этом для распознавания по-прежнему требуется, чтобы ракурс лица был максимально приближен к фронтальному. Набор fda содержит 21 точку;
- Набор mesh на данный момент является самым новым, и содержит 470 3D точек лица. Мы рекомендуем использовать его для получения 3D маски лица.
Набор точек fda. RawSample.getLeftEye возвращает точку 7. RawSample.getRightEye возвращает точку 10 | Набор точек esr. RawSample.getLeftEye возвращает точку 16. RawSample.getRightEye возвращает точку 17 |
---|---|
![]() | ![]() |
Набор точек singlelbf. RawSample.getLeftEye возвращает точку 29. RawSample.getRightEye возвращает точку 30. | Первые 70 точек набора doubleldb (остальные 31 точки взяты из набора singlelbf). RawSample.getLeftEye возвращает точку 68. RawSample.getRightEye возвращает точку 69 |
---|---|
![]() | ![]() |
Набор точек mesh. RawSample.getLeftEye возвращает точку 468. | RawSample.getRightEye возвращает точку 469 |
---|---|
![]() | ![]() |
Расширенный набор точек глаз
Помимо стандартных антропометрических точек лица вы можете получить расширенный набор точек глаз (Iris Landmarks), который включает в себя точки зрачков и век. Возвращаемый вектор состоит из 40 точек для левого и правого глаза в порядке, указанном на изображении ниже. Для каждого глаза возвращается 20 точек: первые 5 точек относятся к зрачку (центр и точки на окружности), остальные 15 точек образуют контур век. Пример отрисовки доступен в демонстрационной программе demo (C++/Java/C#).
Вычисление углов поворота головы
Вычисление углов поворота головы (Pitch, Yaw, Roll) относительно оси наблюдения. Точность определения углов зависит от используемого набора антропометрических точек.
Трекинг лиц (опционально)
Трекингом называют задачу по отслеживанию или сопровождению лиц на видеопотоках. В этом случае помимо детекторов в процессе обработки кадров задействованы трекеры. Трекер представляет собой алгоритм библиотеки libfacerec, который позволяет отслеживать изменения положения лица от кадра к кадру. В результате формируется трек человека (последовательность кадров видеопотока, на которых изображен один и тот же человек). Каждому треку присваивается уникальный идентификатор (track_id), который не меняется с момента обнаружения лица в видеопотоке и до момента его потери.
Реализация детекции лиц
Создание объекта Capturer
Для детекции лиц используется класс Capturer
. При создании объекта класса используется файл конфигурации объекта Capturer, в котором задаются тип используемого детектора и тип используемого набора антропометрических точек (Подробнее в разделе Файлы конфигурации детекторов). Также в файле конфигурации объекта Capturer можно настроить другие параметры, влияющие на качество и скорость работы всего алгоритма. Детектор и набор антропометрических точек указываются в названии файла конфигурации, например: common_capturer_blf_fda_front.xml
- детектор blf, набор точек fda.
Для трекинга используются файлы конфигурации двух типов:
- common_video_capturer - высокая скорость работы, но качество при этом ниже, чем у fda_tracker_capturer
- fda_tracker_capturer - высокое качество, но скорость работы при этом ниже, чем у common_video_capturer
Все доступные файлы конфигурации хранятся в папке conf дистрибутива Face SDK.
Пример 1
Создайте объект Capturer
с помощью метода FacerecService.createCapturer
, передав в качестве аргумента имя файла конфигурации объекта Capturer.
- C++
- C#
- Java
- Python
pbio::Capturer::Ptr capturer = service->createCapturer("common_capturer4.xml");
Capturer capturer = service.createCapturer("common_capturer4_lbf.xml");
final Capturer capturer = service.createCapturer(service.new Config("common_capturer4_lbf.xml"));
capturer = service.create_capturer(Config("common_capturer4_lbf.xml"))
Пример 2
Если при создании Capturer
вам потребуется переопределить значения числовых параметров из файла конфигурации, выполните следующие шаги:
- Создайте объект
FacerecService.Config
, в качестве аргумента передайте имя файла конфигурации. - С помощью метода
Config.overrideParameter
переопределите значения числовых параметров. - Создайте объект
Capturer
с помощью методаFacerecService.createCapturer
, передав объектFacerecService.Config
в качестве аргумента.
- C++
- C#
- Java
- Python
pbio::FacerecService::Config capturer_config("common_capturer4.xml");
capturer_config.overrideParameter("min_size", 200);
pbio::Capturer::Ptr capturer = service->createCapturer(capturer_config);
FacerecService.Config capturerConfig = new FacerecService.Config("common_capturer4_lbf.xml");
capturerConfig.overrideParameter("min_size", 200);
Capturer capturer = service.createCapturer(capturerConfig);
FacerecService.Config capturerConfig = service.new Config("common_capturer4_lbf.xml");
capturerConfig.overrideParameter("min_size", 200);
final Capturer capturer = service.createCapturer(capturerConfig);
capturer_config = Config("common_capturer4_lbf.xml")
capturer_config.override_parameter("min_size", 200)
capturer = service.createCapturer(capturer_config)
Пример 3
Значения некоторых параметров можно изменить в уже созданном объекте Capturer
с помощью метода Capturer.setParameter
.
- C++
- C#
- Java
- Python
pbio::Capturer::Ptr capturer = service->createCapturer("common_capturer4.xml");
capturer->setParameter("min_size", 200);
capturer->setParameter("max_size", 800);
// capturer->capture(...);
// ...
capturer->setParameter("min_size", 100);
capturer->setParameter("max_size", 400);
// capturer->capture(...);
Capturer capturer = service.createCapturer("common_capturer4_lbf.xml");
capturer.setParameter("min_size", 200);
capturer.setParameter("max_size", 800);
// capturer.capturer(...);
// ...
capturer.setParameter("min_size", 100);
capturer.setParameter("max_size", 400);
// capturer.capture(...);
Capturer capturer = service.createCapturer(service.new Config("common_capturer4_lbf.xml"));
capturer.setParameter("min_size", 200);
capturer.setParameter("max_size", 800);
// capturer.capturer(...);
// ...
capturer.setParameter("min_size", 100);
capturer.setParameter("max_size", 400);
// capturer.capture(...);
capturer = service.create_capturer(Config("common_capturer4_lbf.xml"))
capturer.set_parameter("min_size", 200)
capturer.set_parameter("max_size", 800)
# capturer.capturer(...);
# ...
capturer.set_parameter("min_size", 100)
capturer.set_parameter("max_size", 400)
# capturer.capture(...);
Параметры файлов конфигурации объекта Capturer
Нажмите, чтобы отобразить список параметров из файлов конфигурации объекта Capturer, которые могут быть изменены с помощью объекта FacerecService.Config.overrideParameter
Запуск детекции
Подать изображение на вход детектору можно двумя способами:
- Подать данные закодированного изображения в формате JPEG, PNG, TIF или BMP в метод
Capturer.capture
- Подать данные раскодированного изображения в метод
Capturer.capture
, используя классRawImage
Результат выполнения детекции лица сохраняется в интерфейсном объекте RawSample
.
- C++
- C#
- Java
- Python
// чтение изображения
cv::Mat image;
image = cv::imread(image_path, cv::IMREAD_COLOR);
// создание объекта RawImage
cv::Mat input_image;
cv::cvtColor(image, input_image, cv::COLOR_BGR2RGB);
pbio::RawImage input_rawimg(input_image.cols, input_image.rows, pbio::RawImage::Format::FORMAT_RGB, input_image.data);
// выполнение детекции
std::vector<pbio::RawSample::Ptr> samples = capturer->capture(input_rawimg);
// чтение изображения
OpenCvSharp.Mat image = OpenCvSharp.Cv2.ImRead(image_path);
// создание объекта RawImage
byte[] byte_image = new byte[image.Total() * image.Type().Channels];
Marshal.Copy(image.DataStart, byte_image, 0, (int)byte_image.Length);
RawImage input_rawimg = new RawImage(frame.Width, frame.Height, RawImage.Format.FORMAT_BGR, byte_image);
// выполнение детекции
List<RawSample> samples = capturer.capture(input_rawimg);
// чтение изображения
byte[] byte_image;
byte_image = readImage(image_path);
// создание объекта RawImage
RawImage input_rawimg = new RawImage(width, height, RawImage.Format.FORMAT_YUV_NV21, byte_image);
// выполнение детекции
Vector<RawSample> samples = capturer.capture(rawImage);
# чтение изображения
image = cv2.imread(image_path)
# создание объекта RawImage
input_rawimg = RawImage(image.shape[1], image.shape[0], Format.FORMAT_BGR, image.tobytes())
# выполнение детекции
samples = capturer.capture(input_rawimg)
Для трекинга вы также можете вызвать метод Capturer.resetHistory
, чтобы удалить из истории все кадры и лица, и начать отслеживание на новой видеопоследовательности.
Результат детекции
RawSample - это интерфейсный объект, в котором хранится результат детекции. С помощью методов RawSample можно выполнить следующие операции:
- Получить id, назначенный сэмплу лица при детекции (
RawSample.getID
) (только для детекции, совмещенной с трекингом); - Получить степень уверенности детекции (confidence) (для детекторов BLF, REFA и ULD). Для этого необходимо вызвать метод
RawSample.getScore()
, в результате вернется число с плавающей точкой в диапазоне [0, 1]; - Получить ограничивающий прямоугольник лица (
RawSample.getRectangle
), углы поворота головы (RawSample.getAngles
), координаты левого / правого глаза (RawSample.getLeftEye
/RawSample.getRightEye
), антропометрические точки лица (RawSample.getLandmarks
), если лицо расположено фронтально; - Получить расширенный набор точек глаз, который включает в себя точки зрачков и век (
RawSample.getIrisLandmarks()
); - Уменьшить внутреннее изображение лица до предпочтительного размера (
RawSample.downscaleToPreferredSize
); - Сериализовать объект в бинарном формате (
RawSample.save
илиRawSample.saveWithoutImage
), после чего вы можете десериализовать объект методомFacerecService.loadRawSample
илиFacerecService.loadRawSampleWithoutImage
; - Выполнить нормализацию изображения лица с последующей обрезкой (
RawSample.cutFaceImage
илиRawSample.cutFaceRawImage
) (test_facecut).
Объект RawSample можно передать в методы оценки возраста, пола, качества и принадлежности лица реальному человеку (см. Оценка лиц, test_facecut, test_videocap), а также в Recognizer.processing
для создания шаблона (см. Идентификация лиц, test_identify).
Нормализация изображений лиц
Для распознавания и других операций с задетектированными лицами требуется нормализация изображений лиц с последующей обрезкой. Под нормализацией в данном случае имеется в виду разворот лица на изображении во фронтальное положение. Нормализовать лицо можно одним из следующих методов RawSample:
RawSample.cutFaceImage
: нормализованное изображение лица сохраняется в указанный поток (например, в файл), формат кодирования выбирается черезRawSample.ImageFormat
RawSample.cutFaceRawImage
: нормализованное изображение лица возвращается в форматеRawImage
(в нем хранятся незакодированные пиксели изображения в формате RGB/BGR/GRAY (формат выбирается черезRawImage.Format
)
Примеры использования RawSample.cutFaceRawImage
:
- C++
- C#
- Java
- Python
auto raw_image_crop = sample->cutFaceRawImage(
pbio::RawImage::Format::FORMAT_BGR,
pbio::RawSample::FACE_CUT_FULL_FRONTAL);
cv::Mat img_crop(raw_image_crop.height, raw_image_crop.width, CV_8UC3, (void*) raw_image_crop.data);
RawImage raw_image_crop = sample.cutFaceRawImage(RawImage.Format.FORMAT_BGR, RawSample.FaceCutType.FACE_CUT_FULL_FRONTAL);
OpenCvSharp.Mat img_crop = new OpenCvSharp.Mat(raw_image_crop.height, raw_image_crop.width, OpenCvSharp.MatType.CV_8UC3, raw_image_crop.data);
RawImage raw_image_crop = sample.cutFaceRawImage(RawImage.Format.FORMAT_RGB, faceCutType);
int[] pixels = raw_image_crop.getPixels(RawImage.PixelFormat.BITMAP_ARGB_8888);
Bitmap img_crop = Bitmap.createBitmap(pixels, raw_image_crop.width, raw_image_crop.height, Bitmap.Config.ARGB_8888);
raw_image_crop = sample.cut_face_raw_image(Format.FORMAT_GRAY)
img_crop = np.frombuffer(raw_image_crop.data, dtype=np.uint8).reshape([raw_image_crop.height, raw_image_crop.width])
Доступные типы нормализации (RawSample.FaceCutType
):
FACE_CUT_BASE
- базовый (подходит для сэмплов всех типов).FACE_CUT_FULL_FRONTAL
- полный фронтальный ТИП (тип изображения лица) по ГОСТ Р ИСО / МЭК 19794-5 (ISO/IEC 19794-5 Full Frontal) (только для фронтальных сэмплов). Используется для сохранения изображений лица в электронных биометрических документах.FACE_CUT_TOKEN_FRONTAL
- условно фронтальный ТИП (тип изображения лица) по ГОСТ Р ИСО / МЭК 19794-5 (ISO/IEC 19794-5 Token Frontal) (только для фронтальных сэмплов).
Для предварительного просмотра нормализованного изображения лица вызовите метод RawSample.getFaceCutRectangle
, указав тип нормализации. В результате вы получите четыре точки – углы прямоугольника, которые будут использованы для обрезки.
Примеры детекции лиц и нормализации изображений на разных языках программирования доступны в разделе Сэмплы.