Я реалізую адаптацію алгоритму розпізнавання обличчя Віоли-Джонс . Техніка спирається на розміщення підрамника розміром 24x24 пікселів всередині зображення, а згодом розміщення всередині нього прямокутних елементів у кожному положенні з будь-яким можливим розміром.
Ці ознаки можуть складатися з двох, трьох або чотирьох прямокутників. Наведено наступний приклад.
Вони стверджують, що вичерпний набір становить понад 180 тис. (Розділ 2):
Враховуючи, що базова роздільна здатність детектора становить 24x24, вичерпний набір функцій прямокутника досить великий - понад 180 000. Зауважте, що на відміну від бази Хаара, набір об’єктів прямокутника є неповним.
Наступні твердження прямо не зазначені в статті, тому вони є припущеннями з мого боку:
- Є лише 2 об’єкти з двома прямокутниками, 2 об’єкти з трьома прямокутниками та 1 об’єкт із чотирьох прямокутників. Логіка цього полягає в тому, що ми спостерігаємо різницю між виділеними прямокутниками, а не явно колір, яскравість або щось подібне.
- Ми не можемо визначити тип функції A як блок пікселів 1х1; він повинен бути принаймні 1х2 пікселів. Крім того, тип D повинен мати принаймні 2х2 пікселі, і це правило відповідає іншим характеристикам.
- Ми не можемо визначити тип функції A як блок пікселів 1х3, оскільки середній піксель не може бути розділений, і віднімання його від себе ідентично блоку 1х2 пікселя; цей тип функції визначений лише для парних ширин. Крім того, ширина елемента типу 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 . (Зверніть увагу, що це ефективно запобіжить торканню елементів праворуч та / або нижню частину підкадру.)
Тепер, звичайно, питання: чи не допустили вони помилки у своїй реалізації? Чи є сенс розглядати особливості з нульовою поверхнею? Або я бачу це неправильно?