Olej писал(а):
То, что рассматривается в этой теме - только малая часть подобных задач: детектирование компрометации изображения - когда видеокамере подсовывают не собственное лицо, а зафиксированную картинку другой персоны на листе бумаги или, что ещё более актуально, на экране смартфона или планшета.
Суть не в конкретике такой задачи, а в той мощи, которую уже предоставляет проект OpenCV (которая, мощь, оказалась и для меня неожиданной при детальном использовании
) и который проект весьма динамично развивается.
А если коротко отвлечься на конкретную задачу, чтобы к этому больше не возвращаться, а она сама достаточно интересная: нужно детектировать рамку вокруг лица, при том, что она может быть местами разорвана или искажена другим образом.
Можно бы строить нейронный обучаемый классификатор (как, например, придаваемые классификаторы для изображения лица) ... но нужно хорошо отдавать себе отчёт что это потребует: многие тысячи изображений, разделённые на "да" и "нет" и несколько десятков часов машинного времени на обучение (это по описанию опыта тех, кто это проделывал).
Мы пошли другим путём - построить логическую алгоритмику ... которая в результате сотен экспериментов, методом проб и ошибок, последовательными шагами свелась к следующему (что как оказалось тоже достаточно громоздко):
- Алгоритмом LSD (который описан в сообщении от 04 ноя 2016) на изображении строятся отрезки линий...
- Поскольку линии на изображении можно выделять только по градиентам яркости (что и делает LSD) и результаты вероятностные, 1-м шагом отсеиваются (по порогу) линии с сомнительной вероятностью, алгоритм LSD как-раз формирует параметр NFA (Number of False Alarms) для каждого отрезка
- Классификатором определяется область лица (это типовая задача OpenCV), можем считать что это 2D координата центра + некоторый характеристический радиус ... отрезки попадающие внутрь этой области отфильтровываются...
- Вычисляются углы наклона каждого отрезка, для этого удобно далее оперировать со всеми координатами отрезков как с комплексными значениями на 2D плоскости
- Угловые координаты из диапазона (0...2*π) или (-π ...+π) приводятся к диапазону (0...π) — для отрезков 3-го и 4-го квадрантов меняется ориентация начало-конец - это потому, что для наших целей отрезки с наклонами 45, 225, или -135 градусов - идентичны, они параллельны, и рассматривать их раздельно нельзя.
- Следующим критерием отсечения является критерий: отрезок должен лежать в пределах сектора раскрыва из точки центра, вокруг нормали к отрезку, проведенной из этой точки. Проще этот критерий можно сформулировать качественно: отрезок или любое его продолжение не должен проходить через область изображения (или немного расширенную область изображения, умноженную на некоторый коэффициент). Этим отбраковываются радиальные отрезки, ориентированные не вокруг изображения (должны окружать его), а направленные на него. Только введение такой фильтрации позволило избавиться от достаточно частого (показали тестовые прогоны) эффекта «рукав»:
Или, наоборот, клетчатая рубашка может набросать столько отрезков линий, что они без такой фильтрации скомпрометируют любое изображение:
- Следующим этапом все отрезки по углу ориентации кластеризуются (раскладываются) по N угловым кластерам, N — параметр алгоритма, который может меняться в очень широких пределах (6...25), каждый кластер имеет угловой размер ψ=(180/N)ο, причём 1-й кластер — это горизонталь (-ψ/2...+ψ/2). Это и следующий п.9 делается для борьбы с вращением изображения. Вращение можно ожидать в пределах от -45 до +45 градусов , т. е., вообще то говоря, на любой произвольный угол. Мы не можем оперировать такими понятиями как «вертикаль», «горизонталь» в определении направлений!
- Дальше нужно выделить 2 доминантных кластера, представляющих 2 ортогональных направления рамки (это будут координатные оси разыскиваемой рамки ... но это не обязательно 90 градусов). Это связано с тем, что:
а). использовать строго горизонталь и вертикаль для этого нельзя: при вращениях рамки по или против часовой стрелки;
б). использовать строго 90 градусов между кластерами для выбора ортогональных направлений нельзя: при диагональных наклонах рамки (как в аксонометрии):
- Выделяются 2 кластера с преобладающей суммой длин отрезков, принадлежащих кластеру (как вариант алгоритма — просто число отрезков принадлежащих кластеру). Это делается рекурсивным 2-х мерным (по номерам кластеров) поиском (при N=10, например, это требует сравнения 100 попарных гипотез: как вариант, для каждой пары кластеров сумма (длин отрезков, числа отрезков) умножается на sin() угла между централями кластеров, и отбирается пара с максимальным таким значением. Эти 2 преобладающих ортогональных направления остаются для дальнейшего распознавания (оси координат), все отрезки остальных кластеров отбрасываются.
- Дальше делается консолидация детектированных отрезков внутри каждого из 2-х доминантных кластеров: если конец m-го отрезка отстоит от начала m+1-го на некоторый небольшой радиус (это ещё один параметр алгоритма) в смысле евклидовой метрики между координатами, то они объединяются в один, более длинный, отрезок (начало от отрезка m и концом от отрезка m+1). Этот процесс над всеми отрезками кластера нужно выполнять циклически неоднократно (2-3 прохода), до тех пор, пока пригодных для объединения отрезков не останется. Это очередной этап фильтрации отрезков, который позволяет их число сократить на порядок.
Это процесс, в принципе, неоднозначный, в зависимости от того, с какого отрезка начинать консолидацию.
- Дальше оценивается по каждому из 2-х доминантных кластеров асимметрию рассеивания распознанных участков относительно прямоугольника изображения: подсчитывается число отрезков в кластере левее-правее или выше-ниже области изображения лица (как вариант, возможно более правильный — не просто число, а сумма длин отрезков). Т.е. общее число отрезков в кластере n делится на 2 части: «до» и «после» лица, n1+n2=n. Асимметрия затем оценивается как отношение средне-геометрического к средне-арифметическому: А = (n1*n2) / ((n1 + n2)/2) / ((n1 + n2)/2) (можно и извлечь корень квадратный, но это ничего не добавит в смысле распознавания). Эта величина лежит в пределах [0...1] (1 при абсолютно симметричном расположении линий — признак компрометации, 0 — при полной асимметрии, отсутствии компрометации по этой оси). Вот здесь (специально подобранное изображение) нет рамки, поскольку нет асимметрии по вертикали:
- Конечный критерий компрометации (рамки) оценивается как произведение асимметрии по 2-м доминирующим координатам А = A1 * A2.
- Дискриминация пороговая: для изображения без рамки предполагается A=0 или меньше некоторого небольшого (0.1, 0.2, ...) порога (это ещё один параметр алгоритма); для изображения в рамке A>0 (или порога).