Я реализовал адаптацию алгоритма распознавания лиц Виолы-Джонса . Этот метод основан на размещении внутри изображения подкадра размером 24x24 пикселя с последующим размещением внутри него прямоугольных элементов в каждой позиции любого возможного размера.
Эти объекты могут состоять из двух, трех или четырех прямоугольников. Представлен следующий пример.
Они утверждают, что исчерпывающий набор составляет более 180 тысяч (раздел 2):
Учитывая, что базовое разрешение детектора составляет 24x24, исчерпывающий набор функций прямоугольника довольно велик, более 180000. Обратите внимание, что в отличие от базиса Хаара, набор функций прямоугольника является избыточным.
Следующие утверждения явно не указаны в документе, поэтому они являются предположениями с моей стороны:
- Есть только 2 объекта с двумя прямоугольниками, 2 объекта с тремя прямоугольниками и 1 объект с четырьмя прямоугольниками. Логика заключается в том, что мы наблюдаем разницу между выделенными прямоугольниками, а не явно цвет, яркость или что-то в этом роде.
- Мы не можем определить тип объекта A как блок пикселей 1x1; он должен быть не менее 1х2 пикселя. Кроме того, тип 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 . (Обратите внимание, что это эффективно предотвратит соприкосновение элементов с правой и / или нижней частью подрамника.)
Теперь конечно вопрос: ошиблись ли они в своей реализации? Имеет ли смысл рассматривать объекты с нулевой поверхностью? Или я неправильно понимаю?