Контроль качества изображения
Блок контроля качества изображения
Контроль качества изображений лиц позволяет снижать количество ошибок распознавания за счет исключения из пайплайна распознавания изображений лиц недостаточного качества, например, зашумленных, недостаточного размера, повернутых в профиль и др. Биометрические шаблоны, извлечённые из таких изображений, обычно неточно соответствуют персонам в базе, что неизбежно приводит к ошибкам распознавания.
В Face SDK представлены несколько разных подходов к оценке качества, соответсвующих разным модификациями процессинг-блока QUALITY_CONTROL
:
core
— модификация блокаQUALITY_CONTROL
по умолчанию. Выполняет оценку самых важных параметров качества (размер лица, фронтальность, зашумленность изображения и т.п.) для распознавания и оценки Liveness. Результатом является вердикт о прохождении проверок, а также список тех проверок, которые не были пройдены.estimation
— модификация использует специальную нейронную сеть, которая выдаёт численную оценку того, насколько изображение лица подходит для распознавания. Такая оценка позволяет эффективно отфильтровать некачественные изображения, но её результат трудно интерпретировать. То есть нельзя прямо указать, что именно не так с изображением и как его исправить, чтобы повысить оценку. Такую модификацию можно использовать в случаях, когда не обязательно давать конечному пользователю приложения обратную связь, о том, как улучшить фото.
Модификация | Версия | Версия Face SDK | Время детекции CPU (мс)* | Время детекции GPU (мс)** |
---|---|---|---|---|
core | 1 | 3.28 | 39 | 39 |
estimation | 1 | 3.19 | 95 | 5 |
** - GPU (NVIDIA GTX 10xx серия)
Все модификации оценки качества ожидают входной контейнер Context, содержащий бинарное изображение и массив объектов, полученных после работы процессинг-блоков детекции лица и фиттера:
Нажмите, чтобы развернуть спецификацию входного контейнера Context
{
"image" : {
"format": "NDARRAY",
"blob": "data pointer",
"dtype": "uint8_t",
"shape": [height, width, channels]
},
"objects": [{
"id": {"type": "long", "minimum": 0},
"class": "face",
"confidence": {"double", "minimum": 0, "maximum": 1},
"bbox": [x1, y2, x2, y2],
"keypoints": {
"left_eye_brow_left": {"proj" : [x, y]},
"left_eye_brow_up": {"proj" : [x, y]},
"left_eye_brow_right": {"proj" : [x, y]},
"right_eye_brow_left": {"proj" : [x, y]},
"right_eye_brow_up": {"proj" : [x, y]},
"right_eye_brow_right": {"proj" : [x, y]},
"left_eye_left": {"proj" : [x, y]},
"left_eye": {"proj" : [x, y]},
"left_eye_right": {"proj" : [x, y]},
"right_eye_left": {"proj" : [x, y]},
"right_eye": {"proj" : [x, y]},
"right_eye_right": {"proj" : [x, y]},
"left_ear_bottom": {"proj" : [x, y]},
"nose_left": {"proj" : [x, y]},
"nose": {"proj" : [x, y]},
"nose_right": {"proj" : [x, y]},
"right_ear_bottom": {"proj" : [x, y]},
"mouth_left": {"proj" : [x, y]},
"mouth": {"proj" : [x, y]},
"mouth_right": {"proj" : [x, y]},
"chin": {"proj" : [x, y]},
"points": {"proj" : [x, y]}
}
}]
}
Модификация core
Cоздание процессинг-блока модификации core
происходит также, как и у любого другого блока, однако в нем есть ряд парметров, специфичных именно для этой модификации:
{
"unit_type": "QUALITY_CONTROL",
"modification": "core",
"version": 1,
"mode": ["recognition", "liveness"],
"preset": {"minimal", "optimal", "maximum"},
"{check_name}_threshold": 0
}
Рассмотрим подробнее специфичные параметры:
"mode" — требуется передать массив строк, в котором задаются режимы работы блока. На данный момент доступны режимы "liveness" и "recognition". Передайте оба, либо одно из этих значений. Режимы отличаются наборами проверок, а также значениями порогов по умолчанию.
"preset" — принимает на вход одно из трех значений: "minimal", "optimal", "maximum". Значение, переданное в "preset" определяет конкретные величины порогов при проверке:
- "minimal" — соответствует самым нетребовательным пороговым значениям. Подходит для большинства сценариев применения, позволяет отфильтровать небольшое число изображений.
- "optimal" — соответствует средним пороговым значениям. Подходит для сценариев, где в целом не ожидается проблем с качеством изображения, позволяет отфильтровать большее число изображений, обеспечивая при этом значительное снижение ошибок.
- "maximum" — соответствует самым требовательным к качеству значениям порогов. Подходит для сценариев, где требуется получение изображения максимального качества, позволяет отфильтровать самое большое число некачественных изображений.
Также, существует возможность отрегулировать порог конкретной проверки, передав в Context параметр вида "{check_name}_threshold" и соответствующее числовое значение. Пример такого параметра — "eyes_distance_check": 42.
Ниже приведена таблица со списком проверок, реализуемых в модификации core
, а также пороговые значения, соответствующие разным пресетам. Обратите внимание, что при работе обоих режимов одновременно все проверки включены.
В случае, если проверка присутствует и в режиме "liveness", и в режиме "recognition", выбирается наиболее высокий порог.
- Качество для распознавания
- Качество для Liveness
Проверка | Оцениваемый параметр | Порог minimal | Порог optimal | Порог maximum |
---|---|---|---|---|
noise | Максимально допустимая зашумленность изображения в баллах от 0 до 1 | 0.21 | 0.4 | 0.5 |
dynamic_range | Максимально допустимый динамический диапазон интенсивности в баллах от 0 до 2.55 | 0.72 | 0.96 | 1.36 |
sharpness | Максимально допустимая резкость изображения в баллах от 0 до 1S | 0.09 | 0.19 | 0.33 |
pitch | Максимально допустимый поворот лица по оси pitch в градусах | 44 | 33 | 23 |
yaw | Максимально допустимый поворот лица по оси yaw в градусах | 63 | 50 | 50 |
face_overflow | Выход лица за границу изображения в в баллах от 0 до 1 | 0.0 | 0.0 | 0.0 |
eye_distance | Расстояние между центрами глаз в пикселях | 25 | 35 | 35 |
Проверка | Оцениваемый параметр | Порог minimal | Порог optimal | Порог maximum |
---|---|---|---|---|
noise | Максимально допустимая зашумленность изображения в баллах от 0 до 1 | 0.32 | 0.5 | 0.5 |
dynamic_range | Максимально допустимый динамический диапазон интенсивности в баллах от 0 до 2.55 | 0.5 | 0.7 | 1.2 |
sharpness | Максимально допустимая резкость изображения в баллах от 0 до 1S | 0.1 | 0.14 | 0.2 |
pitch | Максимально допустимый поворот лица по оси pitch в градусах | 30 | 30 | 20 |
yaw | Максимально допустимый поворот лица по оси yaw в градусах | 44 | 28 | 28 |
face_overflow | Выход лица за границу изображения в в баллах от 0 до 1 | 0.0 | 0.0 | 0.0 |
glasses | Оценка наличия солнечных очков в баллах от 0 до 1 | 0.95 | 0.95 | 0.95 |
face_size_on_image | Минимальная доля площади лица относительно всего изображения | 0.011 | 0.013 | 0.013 |
gray_scale | Проверка на то, является ли изображение цветным. Не конфигурируется | - | - | - |
На графиках ниже показано, на примере режима "recognition", как некоторые проверки при различных значениях порога влияют на ошибку распознавания FRR при фиксированном FAR=10E-6. Графики построены на внутренних датасетах 3DiVi, которые соответствуют сценариям удаленной идентификации и кооперативного СКУД.
- pitch
- yaw
- sharpness
- noise
- dynamic_range
Спецификация выходного контейнера
После вызова процессинг-блока оценки качества каждому объекту из массива "objects"
будут добавлены соответствующие атрибуты. Формат выходного контейнер Context модификации core
выглядит следующим образом:
{
"quality": {
"value": {"type": "boolean"} // true — все проверки успешно пройдены, false — есть непройденные проверки.
"failed_checks":[ // список проверок, по которым изображение не проходит, если value==true, список пуст
{"check": {check_name}, // название проверки
"result": {chec_value}, // значение проверки
},
...
]
}
Модификация estimation
В модификации "estimation"
используется специализированная нейронная сеть, которая оценивает качество изображения в целом. Сеть обучена минимизировать количество ошибок распознавания, а результатом проверки является "confidence"
— число от 0 (худшее качество) до 1 (идеальное качество).
Важно: при обучении нейронная сеть ориентировалась не на субъективное восприятие качества человеком и не на стандарты ISO, а на сокращение числа ошибок распознавания. Поэтому confidence
может быть сложно интерпретировать.
Рекомендуется использовать эту модификацию только когда не требуется взаимодействие с пользователем. В случаях, например, удалённой идентификации или СКУД, чаще выбирают модификацию core
.
- 0.01 — Базовый фильтр. Отбрасываются только самые некачественные изображения. Рекомендуется для большинства сценариев, где важно не потерять лица пользователей.
- 0.1 — Более строгий вариант. Подходит для систем, где допустима несколько небольшая потеря детекций ради повышения надежности распознавания.
- 0.4 — Оптимальный баланс для сценариев с высокими требованиями к качеству и большим потоком данных (например, для контроля доступа или поиска в больших базах).
Спецификация процессинг-блока оценки качества
После вызова процессинг-блока оценки качества, каждому объекту из массива "objects"
будут добавлены соответствующие атрибуты.
{
"quality": {
"value": {"type": "boolean"}, // Пройдена ли проверка по пороговому значению confidence
"confidence" : {"type": "double", "minimum": 0, "maximum": 1} // 0 - самое плохое качество, 1 - наилучшее качество
}
}
Пример работы процессинг-блока
Создайте конфигурационный контейнер Context и укажите значения
"unit_type"
,"modification"
,"version"
для нужного вам блока. Пример создания процессинг-блока можно найти на странице Работа с процессинг-блоком.Передайте контейнер-контекст, полученный после работы процессинг-блоков детектора и фиттера.
Вызовете процессинг-блок оценки.
Получите результат работы процессинг-блока.
- C++
- Python
- Flutter
- C#
- Java
- Kotlin
- NodeJS
- Go
auto configCtx = service->createContext();
configCtx["unit_type"] = "QUALITY_CONTROL";
pbio::ProcessingBlock blockQuality = service->createProcessingBlock(configCtx);
//------------------
// создание процессинг-блока и контейнера Context с бинарным изображением
//------------------
faceDetector(ioData);
faceFitter(ioData);
blockQuality(ioData);
bool passed = ioData["objects"][0]["quality"]["value"].getBool;
configCtx = {"unit_type": "QUALITY_CONTROL"}
blockQuality = service.create_processing_block(configCtx)
#------------------
# создание процессинг-блока и контейнера Context с бинарным изображением
#------------------
faceDetector(ioData)
faceFitter(ioData)
blockQuality(ioData)
passed = ioData["objects"][0]["quality"]["value"].get_value()
ProcessingBlock blockQuality = service.createProcessingBlock({"unit_type": "QUALITY_CONTROL"});
//------------------
// создание процессинг-блока и контейнера Context с бинарным изображением
//------------------
faceDetector.process(ioData);
faceFitter.process(ioData);
blockQuality.process(ioData);
bool passed = ioData["objects"][0]["quality"]["value"].get_value();
Dictionary<object, object> configCtx = new();
configCtx["unit_type"] = "QUALITY_CONTROL";
ProcessingBlock blockQuality = service.CreateProcessingBlock(configCtx);
//------------------
// создание процессинг-блока оценки лица и Context-контейнера с бинарным изображением
//------------------
faceDetector.Invoke(ioData);
faceFitter.Invoke(ioData);
blockQuality.Invoke(ioData);
bool passed = ioData["objects"][0]["quality"]["value"].GetBool();
Context configCtx = service.createContext();
configCtx.get("unit_type").setString("QUALITY_CONTROL");
ProcessingBlock blockQuality = service.createProcessingBlock(configCtx);
//------------------
// создание процессинг-блока оценки лица и Context-контейнера с бинарным изображением
//------------------
faceDetector.process(ioData);
faceFitter.process(ioData);
blockQuality.process(ioData);
boolean passed = ioData.get("objects").get(0).get("quality").get("value").getBool();
val configCtx = service.createContext()
configCtx["unit_type"].string = "QUALITY_CONTROL"
val blockQuality = service.createProcessingBlock(configCtx)
//------------------
// создание процессинг-блока оценки лица и Context-контейнера с бинарным изображением
//------------------
faceDetector.process(ioData)
faceFitter.process(ioData)
blockQuality.process(ioData)
val passed = ioData["objects"][0]["quality"]["value"].boolean
let configCtx = new facerec.Context();
configCtx.get("unit_type").value = "QUALITY_CONTROL";
let blockQuality = new facerec.ProcessingBlock(configCtx);
//------------------
// создание процессинг-блока оценки лица и Context-контейнера с бинарным изображением
//------------------
faceDetector.process(ioData);
faceFitter.process(ioData);
blockQuality.process(ioData);
let passed = ioData.get("objects").get(0).get("quality").get("value").value
configContext, err := facesdk.CreateContext()
context, err := configContext.GetOrInsertByKey("unit_type")
err = context.SetString("QUALITY_CONTROL")
defer configContext.Close()
blockQuality, err := service.CreateProcessingBlock(configContext)
defer blockQuality.Close()
//------------------
// создание процессинг-блока оценки лица и Context-контейнера с бинарным изображением
//------------------
err = faceDetector.Process(ioData);
err = faceFitter.Process(ioData);
err = blockQuality.Process(ioData);
context, err = ioData.GetByKey("objects")
context, err = context.GetByIndex(0)
context, err = context.GetByKey("quality")
context, err = context.GetByKey("value")
passed, err = context.GetBool()