Я реализую адаптацию алгоритм обнаружения лица Виолы-Джонса. Эта технология основана на размещении подкадра в 24х24 пикселя внутри изображения и последующем размещении в нем прямоугольных элементов в каждой позиции с любым размером.
Эти функции могут состоять из двух, трех или четырех прямоугольников. Представлен следующий пример.
Они утверждают, что исчерпывающий набор более 180k (раздел 2):
Учитывая, что базовое разрешение детектора равно 24x24, исчерпывающий набор элементов прямоугольника довольно большой, более 180 000. Обратите внимание, что в отличие от основания Хаара набор прямоугольников функции являются неполными.
Следующие утверждения явно не указаны в документе, поэтому они являются предположениями с моей стороны:
- Есть только 2 двух прямоугольника, 2 трех прямоугольника и 1 функция с четырьмя прямоугольниками. Логика этого заключается в том, что мы наблюдаем разницу между выделенными прямоугольниками, а не явно цвет или яркость или что-то в этом роде.
- Мы не можем определить тип функции A как 1x1 пиксельный блок; он должен иметь по крайней мере 1x2 пикселя. Кроме того, тип D должен быть не менее 2x2 пикселя, и это правило выполняется в соответствии с другими функциями.
- Мы не можем определить тип функции A как блок пикселя 1x3, поскольку средний пиксель не может быть разбит на разделы, а вычесть его из себя идентично блоку пикселов 1x2; этот тип функции определяется только для равномерной ширины. Кроме того, ширина типа функции C должна быть делимой на 3, и это правило выполняется в соответствии с другими функциями.
- Мы не можем определить функцию с шириной и/или высотой 0. Поэтому мы перебираем x и y на 24 минус размер функции.
Исходя из этих предположений, я подсчитал исчерпывающий набор:
const int frameSize = 24;
const int features = 5;
// All five feature types:
const int feature[features][2] = {{2,1}, {1,2}, {3,1}, {1,3}, {2,2}};
int count = 0;
// Each feature:
for (int i = 0; i < features; i++) {
int sizeX = feature[i][0];
int sizeY = feature[i][1];
// Each position:
for (int x = 0; x <= frameSize-sizeX; x++) {
for (int y = 0; y <= frameSize-sizeY; y++) {
// Each size fitting within the frameSize:
for (int width = sizeX; width <= frameSize-x; width+=sizeX) {
for (int height = sizeY; height <= frameSize-y; height+=sizeY) {
count++;
}
}
}
}
}
Результат 162,336.
Единственный способ, который я нашел, чтобы приблизиться к "более 180 000", о которых говорят Виола и Джонс, - это предположение № 4 и введение ошибок в код. Это включает в себя изменение четырех строк соответственно:
for (int width = 0; width < frameSize-x; width+=sizeX)
for (int height = 0; height < frameSize-y; height+=sizeY)
В результате получается 180,625. (Обратите внимание, что это эффективно предотвратит, когда функции будут касаться правой и/или нижней части подкадра.)
Теперь, конечно, вопрос: допустили ли они ошибку в их реализации? Имеет ли смысл рассматривать объекты с поверхностью нуля? Или я вижу это неправильно?