Розпізнавання обличчя Віоли-Джонс вимагає 180 тис. Функцій


84

Я реалізую адаптацію алгоритму розпізнавання обличчя Віоли-Джонс . Техніка спирається на розміщення підрамника розміром 24x24 пікселів всередині зображення, а згодом розміщення всередині нього прямокутних елементів у кожному положенні з будь-яким можливим розміром.

Ці ознаки можуть складатися з двох, трьох або чотирьох прямокутників. Наведено наступний приклад.

Особливості прямокутника

Вони стверджують, що вичерпний набір становить понад 180 тис. (Розділ 2):

Враховуючи, що базова роздільна здатність детектора становить 24x24, вичерпний набір функцій прямокутника досить великий - понад 180 000. Зауважте, що на відміну від бази Хаара, набір об’єктів прямокутника є неповним.

Наступні твердження прямо не зазначені в статті, тому вони є припущеннями з мого боку:

  1. Є лише 2 об’єкти з двома прямокутниками, 2 об’єкти з трьома прямокутниками та 1 об’єкт із чотирьох прямокутників. Логіка цього полягає в тому, що ми спостерігаємо різницю між виділеними прямокутниками, а не явно колір, яскравість або щось подібне.
  2. Ми не можемо визначити тип функції A як блок пікселів 1х1; він повинен бути принаймні 1х2 пікселів. Крім того, тип D повинен мати принаймні 2х2 пікселі, і це правило відповідає іншим характеристикам.
  3. Ми не можемо визначити тип функції A як блок пікселів 1х3, оскільки середній піксель не може бути розділений, і віднімання його від себе ідентично блоку 1х2 пікселя; цей тип функції визначений лише для парних ширин. Крім того, ширина елемента типу C повинна ділитися на 3, і це правило відповідає іншим характеристикам.
  4. Ми не можемо визначити об’єкт із шириною та / або висотою 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 . (Зверніть увагу, що це ефективно запобіжить торканню елементів праворуч та / або нижню частину підкадру.)

Тепер, звичайно, питання: чи не допустили вони помилки у своїй реалізації? Чи є сенс розглядати особливості з нульовою поверхнею? Або я бачу це неправильно?


Чому я отримую count = 114829, коли я запускаю ваш код?
Нікі

Чому ваші цикли x / y починаються з 1? Я припускаю, що x / y є верхньою лівою координатою прямокутника об’єкта. Чи не слід тоді x / y починати з 0/0?
Нікі

Окрім того, починається він з 0 або 1, закінчуючись на, x < sizeце пов’язано з припущенням №4: Я хочу, щоб функція залишалася в підкадрі, але мала розмір принаймні 1х1. Щодо того, чи має розмір ознаки виходити за межі підкадру, ну, можливо, це теж припущення.
Пол Ламмертсма,

Подібним чином, якби я почав х з 0, йому довелося б бігти до x < size - 1, тож виграшу немає.
Пол Ламмертсма,

Я зробив мільйон для петель. мені це здається неправильним. <розмір не дозволить x ніколи не стати 24, починаючи з 0 дасть вам 0 ... 23, При розмірі 1 піксель в ширину, прямокутник ніколи не покине рамку.
Бретон

Відповіді:


40

При детальному розгляді ваш код здається мені правильним; що змушує замислитись, чи не було у оригінальних авторів помилок окремо. Думаю, хтось повинен поглянути, як OpenCV це реалізує!

Тим не менше, одна пропозиція полегшити розуміння - перевернути порядок циклів for, спершу переглянувши всі розміри, а потім зациклювавши можливі місця з урахуванням розміру:

#include <stdio.h>
int main()
{
    int i, x, y, sizeX, sizeY, width, height, count, c;

    /* All five shape types */
    const int features = 5;
    const int feature[][2] = {{2,1}, {1,2}, {3,1}, {1,3}, {2,2}};
    const int frameSize = 24;

    count = 0;
    /* Each shape */
    for (i = 0; i < features; i++) {
        sizeX = feature[i][0];
        sizeY = feature[i][1];
        printf("%dx%d shapes:\n", sizeX, sizeY);

        /* each size (multiples of basic shapes) */
        for (width = sizeX; width <= frameSize; width+=sizeX) {
            for (height = sizeY; height <= frameSize; height+=sizeY) {
                printf("\tsize: %dx%d => ", width, height);
                c=count;

                /* each possible position given size */
                for (x = 0; x <= frameSize-width; x++) {
                    for (y = 0; y <= frameSize-height; y++) {
                        count++;
                    }
                }
                printf("count: %d\n", count-c);
            }
        }
    }
    printf("%d\n", count);

    return 0;
}

з тими ж результатами, що і попередні 162336


Щоб перевірити це, я протестував корпус вікна 4x4 і вручну перевірив усі випадки (легко підрахувати, оскільки форми 1x2 / 2x1 та 1x3 / 3x1 однакові, обертаються лише на 90 градусів):

2x1 shapes:
        size: 2x1 => count: 12
        size: 2x2 => count: 9
        size: 2x3 => count: 6
        size: 2x4 => count: 3
        size: 4x1 => count: 4
        size: 4x2 => count: 3
        size: 4x3 => count: 2
        size: 4x4 => count: 1
1x2 shapes:
        size: 1x2 => count: 12             +-----------------------+
        size: 1x4 => count: 4              |     |     |     |     |
        size: 2x2 => count: 9              |     |     |     |     |
        size: 2x4 => count: 3              +-----+-----+-----+-----+
        size: 3x2 => count: 6              |     |     |     |     |
        size: 3x4 => count: 2              |     |     |     |     |
        size: 4x2 => count: 3              +-----+-----+-----+-----+
        size: 4x4 => count: 1              |     |     |     |     |
3x1 shapes:                                |     |     |     |     |
        size: 3x1 => count: 8              +-----+-----+-----+-----+
        size: 3x2 => count: 6              |     |     |     |     |
        size: 3x3 => count: 4              |     |     |     |     |
        size: 3x4 => count: 2              +-----------------------+
1x3 shapes:
        size: 1x3 => count: 8                  Total Count = 136
        size: 2x3 => count: 6
        size: 3x3 => count: 4
        size: 4x3 => count: 2
2x2 shapes:
        size: 2x2 => count: 9
        size: 2x4 => count: 3
        size: 4x2 => count: 3
        size: 4x4 => count: 1

Переконливо. Настільки переконливий, що я досить впевнений, що ми маємо рацію. Я надіслав автору електронне повідомлення, щоб перевірити, чи не допустив я якоїсь принципової помилки в своїх міркуваннях. Ми побачимо, чи встигне хлопець, який зайнятий, відповісти.
Пол Ламмертсма,

майте на увазі, ця річ виходить вже пару років, і з того часу було зроблено багато поліпшень
Амро

25
Оригінальний документ, де було зазначено 180 тис., Походить від матеріалів конференції 2001 р. З питань комп’ютерного зору та розпізнавання образів. У переглянутий статті, прийнятій у 2003 р. Та опублікованій у Міжнародному журналі комп'ютерного зору у 2004 р., Зазначено на с. 139 (кінець розділу 2): "вичерпний набір прямокутників досить великий, 160 000". Схоже, ми мали рацію!
Пол Ламмертсма,

3
Чудово, дякую за оновлення. Для тих , хто зацікавлений, я знайшов посилання на IJCV'04 паперу: lear.inrialpes.fr/people/triggs/student/vj/viola-ijcv04.pdf
Amro

Так, це все. 160 тис., А не 180 тис.
Пол Ламмертсма,

9

всі. У газетах Віоли та Джонса все ще є певна плутанина.

У їх роботі CVPR'01 це чітко зазначено

"Більш конкретно, ми використовуємо три типи об’єктів. Значення об’єкта з двома прямокутниками - це різниця між сумою пікселів у двох прямокутних областях. Регіони мають однаковий розмір і форму і сусідні по горизонталі або вертикалі (див. Малюнок 1). Елемент із трьох прямокутників обчислює суму в межах двох зовнішніх прямокутників, віднятих із суми в центральному прямокутнику. Нарешті, елемент із чотирьох прямокутників ".

У статті IJCV'04 сказано точно те саме. Отже, 4 особливості . Але як не дивно, цього разу вони заявили, що вичерпним набором функцій є 45396! Здається, це не остаточна версія. Тут я думаю, що там були введені деякі додаткові обмеження, такі як min_width, min_height, співвідношення ширина / висота і навіть положення.

Зверніть увагу, що обидві статті можна завантажити на його веб-сторінці .


3

Не прочитавши всю статтю, формулювання вашої цитати стирчить мені

Враховуючи, що базова роздільна здатність детектора становить 24x24, вичерпний набір функцій прямокутника досить великий - понад 180 000. Зауважте, що на відміну від бази Хаара, набір об’єктів прямокутника є неповним.

"Набір об’єктів прямокутника переповнений" "Вичерпний набір"

для мене це звучить як налаштування, де я очікую, що автор статті докладе пояснення щодо того, як вони відбирають пошуковий простір до більш ефективного набору, наприклад, позбувшись таких тривіальних випадків, як прямокутники з нулем область поверхні.

редагувати: або за допомогою якогось алгоритму машинного навчання, як натякає реферат. Вичерпний набір передбачає усі можливості, а не лише "розумні".


Я повинен включити виноску після "overcomplete": "Повна основа не має лінійної залежності між елементами бази і має таку ж кількість елементів, як і простір зображення, в даному випадку 576. Повний набір з 180 000 тис. Функцій багаторазово перевищує завершено ". Вони явно не позбавляються класифікаторів без поверхні, вони використовують AdaBoost, щоб визначити, що "дуже мала кількість цих функцій може бути об'єднана, щоб сформувати ефективний класифікатор". Гаразд, отже, функції з нульовою поверхнею негайно відкинуть, але навіщо їх розглядати в першу чергу?
Пол Ламмертсма,

Ну це звучить як міркування когось насправді в теорії множин.
Бретон

Я згоден, що вичерпний набір передбачає всі можливості. Але враховуйте, що якщо взяти від 1 до 24 для x та ширини <= x, функція розширить 1 піксель за межі підкадру!
Пол Ламмертсма,

Ви впевнені, що ваш код не заповнений помилками "вимкнено одним"? Я просто придивився уважніше, і у вас, звичайно, є кумедний спосіб написання циклу for.
Бретон

Я мав би це визнати - я просто трохи продумав, і якщо у вас є прямокутник заввишки 1 піксель, 2 пікселі заввишки, 3 пікселі заввишки, аж до 24 пікселів, у вас є 24 види прямокутника, усі який вміщується у підкадр висотою 24 пікселі. Які звиси?
Бретон,

2

Немає жодної гарантії, що будь-який автор будь-якої статті є правильним у всіх своїх припущеннях і висновках. Якщо ви вважаєте, що припущення №4 є дійсним, то дотримуйтесь цього припущення і спробуйте свою теорію. Ви можете бути успішнішими за оригінальних авторів.


Експерименти показують, що він виконує, здавалося б, абсолютно однакове. Я вважаю, що AdaBoost просто відмовляється від цих додаткових функцій нульової поверхні в першому циклі, але насправді я цього не вивчав.
Пол Ламмертсма,

Віола та Джонс - дуже відомі імена в галузі комп'ютерного зору. Насправді ця конкретна стаття вважається фундаментальною. Кожен робить помилки, але, як було доведено, саме цей алгоритм працює дуже добре.
Діма

1
Безумовно, і я взагалі не сумніваюся в їх методі. Це ефективно і працює дуже добре! Теорія обґрунтована, але я вважаю, що вони могли помилково обрізати свій детектор на один піксель і включити непотрібні функції нульової поверхні. Якщо ні, я закликаю вас продемонструвати 180 тис. Функцій!
Пол Ламмертсма,

Справа в тому, що всі люди. Всі роблять помилки. Коли велике ім'я робить помилки, вони часто криються поколіннями, бо люди бояться сумніватися в отриманій мудрості. Але справжня наука дотримується наукового методу і нікому не поклоняється, яким би великим їх не звали. Якщо це наука, то прості смертні можуть докласти зусиль, зрозуміти, як це працює, і адаптувати це до своїх обставин.
Майкл Діллон,

Ми побачимо; Я надіслав електронне повідомлення автору.
Пол Ламмертсма,

1

Цілком гарне спостереження, але вони можуть неявно обнулити кадр 24x24 або "перелитися" і почати використовувати перші пікселі, коли це виходить за межі, як при обертальних зміщеннях, або, як сказав Бретон, вони можуть розглядати деякі функції як "тривіальні особливості" а потім відкиньте їх за допомогою AdaBoost.

Крім того, я написав версії вашого коду на Python та Matlab, щоб я міг протестувати сам код (простіше налагоджувати та стежити за мною), і тому я публікую їх тут, якщо комусь вони колись знадобляться корисними.

Python:

frameSize = 24;
features = 5;
# All five feature types:
feature = [[2,1], [1,2], [3,1], [1,3], [2,2]]

count = 0;
# Each feature:
for i in range(features):
    sizeX = feature[i][0]
    sizeY = feature[i][1]
    # Each position:
    for x in range(frameSize-sizeX+1):
        for y in range(frameSize-sizeY+1):
            # Each size fitting within the frameSize:
            for width in range(sizeX,frameSize-x+1,sizeX):
                for height in range(sizeY,frameSize-y+1,sizeY):
                    count=count+1
print (count)

Matlab:

frameSize = 24;
features = 5;
% All five feature types:
feature = [[2,1]; [1,2]; [3,1]; [1,3]; [2,2]];

count = 0;
% Each feature:
for ii = 1:features
    sizeX = feature(ii,1);
    sizeY = feature(ii,2);
    % Each position:
    for x = 0:frameSize-sizeX
        for y = 0:frameSize-sizeY
            % Each size fitting within the frameSize:
            for width = sizeX:sizeX:frameSize-x
                for height = sizeY:sizeY:frameSize-y
                    count=count+1;
                end
            end
        end
    end
end

display(count)

Чому ви використовуєте 5 функцій, лише 4 розміщені в основному питанні. Але все одно дякую за версію python.
Каспаров92,

0

У своїй оригінальній статті 2001 року вони лише зазначають, що використовуються три типи функцій:

ми використовуємо три типи функцій

Також

Регіони мають однакові розміри та форму

Оскільки кожен вид має дві орієнтації, розумно припустити, що вони використовують загалом 6 об’єктів (принаймні для обчислення загальної кількості об’єктів): 2 об’єкти з двома прямокутниками, 2 об’єкти з трьома прямокутниками та 2 об’єкти з чотирма прямокутниками. З огляду на це, насправді існує понад 180 000 функцій:

feature_types = [(1,2), (2,1), (1,3), (3,1), (2,2), (2,2)]
window_size = (24,24)

total_features = 0
for f_type in feature_types:
    for f_height in range(f_type[0], window_size[0] + 1, f_type[0]):
        for f_width in range(f_type[1], window_size[1] + 1, f_type[1]):
            total_features += (window_size[0] - f_height + 1) * (window_size[1] - f_width + 1)
            
print(total_features)
# 183072

Якщо ви упустите один тип об’єктів із чотирма прямокутниками (що, мабуть, має місце в їх подальшій публікації), то загальна кількість об’єктів - 162 336.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.