Question

J'ai une adaptation de la mise en œuvre Viola-Jones algorithme de détection de visage . La technique repose sur une sous-trame de placer 24x24 pixels dans une image, et par la suite placer les caractéristiques rectangulaires à l'intérieur dans toutes les positions de toutes les tailles possibles.

Ces caractéristiques peuvent être constitués de deux, trois ou quatre rectangles. L'exemple suivant est présenté.

Caractéristiques du rectangle

Ils prétendent l'ensemble exhaustive est supérieure à 180K (section 2):

  

Étant donné que la résolution de base du détecteur est 24x24, l'ensemble exhaustif de caractéristiques du rectangle est assez grand, plus de 180.000. Notez que contrairement à la base de Haar, l'ensemble du rectangle   caractéristiques est surcomplets.

Les énoncés suivants ne sont pas explicitement mentionnées dans le document, ils sont donc des hypothèses de ma part:

  1. Il y a seulement 2 caractéristiques de deux rectangle, 2 trois caractéristiques rectangle et 1 fonction de quatre rectangle. La logique derrière cela est que nous observons différence entre les rectangles mis en évidence, pas explicitement la couleur ou la luminance ou quelque chose de ce genre.
  2. Nous ne pouvons pas définir fonction de type A comme un bloc de pixels 1x1; il doit au moins être d'au moins 1x2 pixels. En outre, le type D doit être au moins de pixels 2x2, et cette règle tient donc aux autres fonctions.
  3. Nous ne pouvons pas définir fonction de type A comme un bloc de pixels 1x3 comme le pixel milieu ne peut pas être divisée, et en la soustrayant de lui-même est identique à un bloc de pixels 1x2; ce type de fonction est définie que pour des largeurs même. En outre, la largeur du type de fonction C doit être divisible par 3, et cette règle tient donc aux autres fonctions.
  4. Nous ne pouvons pas définir une fonction avec une largeur et / ou la hauteur de 0. Par conséquent, nous parcourons x et y à 24 moins la taille de la fonction.

Sur la base de ces hypothèses, j'ai compté l'ensemble exhaustif:

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++;
                }
            }
        }
    }
}

Le résultat est 162336 .

La seule manière que je trouvais à se rapprocher de la « plus de 180.000 » Viola & Jones parle, est en baisse hypothèse # 4 et en introduisant des bugs dans le code. Cela implique de changer respectivement quatre lignes:

for (int width = 0; width < frameSize-x; width+=sizeX)
for (int height = 0; height < frameSize-y; height+=sizeY)

Le résultat est alors 180625 . (Notez que cela empêchera effectivement les caractéristiques de toucher jamais le droit et / ou en bas du sous-châssis.)

Maintenant, bien sûr la question: ont-ils fait une erreur dans leur mise en œuvre? Est-il raisonnable de tenir compte des caractéristiques avec une surface de zéro? Ou suis-je le vois dans le mauvais sens?

Était-ce utile?

La solution

À regarder de plus près, votre code semble correct pour moi; qui on se demande si les auteurs originaux avaient un hors par un bug. Je suppose que quelqu'un doit regarder comment OpenCV implémente!

Néanmoins, une suggestion pour le rendre plus facile à comprendre est de retourner l'ordre du pour boucles en allant sur toutes les tailles d'abord, en boucle puis sur les emplacements possibles compte tenu de la taille:

#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;
}

avec les mêmes résultats que le précédent 162336


Pour le vérifier, je l'ai testé le cas d'une fenêtre 4x4 et vérifié manuellement tous les cas (facile à compter depuis des formes 1x2 / 2x1 et 1x3 / 3x1 sont les mêmes que 90 degrés) mis en rotation:

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

Autres conseils

tous. Il y a encore une certaine confusion dans les papiers de Viola et Jones.

Dans leur document de CVPR'01 il est clairement indiqué que

  

"Plus précisément, nous utilisons trois   types de fonctions. La valeur d'une    fonction de deux rectangle est la différence entre la somme des   pixels dans les deux zones rectangulaires.   Les régions ont la même taille et   forme et sont horizontalement ou   verticalement adjacent (voir Figure 1).    Une caractéristique de trois rectangle calcule la somme dans les deux à l'extérieur   rectangles soustraits de la somme de   un rectangle central. Enfin a   fonction de quatre rectangle ».

Dans le document de IJCV'04, exactement la même chose est dit. Donc, au total, 4 caractéristiques . Mais assez curieusement, ils ont dit cette fois que le jeu de fonctionnalités exhaustives est 45396! Cela ne semble pas être la version.Here finale, je suppose que certaines contraintes supplémentaires ont été introduites là, comme MIN_WIDTH, MIN_HEIGHT, rapport largeur / hauteur, et même la position.

Notez que les deux documents sont téléchargeables sur sa page .

Ayant pas lu tout le document, le libellé de votre citation dépasse moi

  

Étant donné que la résolution de base de la   détecteur est 24x24, l'ensemble exhaustive   des caractéristiques du rectangle est assez grand,   plus de 180.000. Notez que contrairement à la   base de Haar, l'ensemble du rectangle   caractéristiques est surcomplets.

« L'ensemble des caractéristiques du rectangle est surcomplets » "Set Exhaustive"

il me semble comme un mis en place, où je pense l'auteur du papier à suivre avec une explication pour la façon dont ils cull l'espace de recherche à un ensemble plus efficace, par exemple, se débarrasser des cas insignifiants, comme rectangles avec zéro zone de surface.

edit: ou en utilisant une sorte d'algorithme d'apprentissage automatique, comme les conseils abstraits à. ensemble implique toutes les possibilités Exhaustif, pas seulement les « raisonnables ».

Il n'y a aucune garantie que l'auteur d'un document est correct dans toutes leurs hypothèses et conclusions. Si vous pensez cette hypothèse n ° 4 est valide, garder cette hypothèse, et essayer votre théorie. Vous pouvez avoir plus de succès que les auteurs originaux.

Très bonne observation, mais ils pourraient implicitement zéro pad le cadre 24x24, ou « débordement » et commencer à utiliser les premiers pixels quand il est hors des limites, comme dans les changements de rotation, ou Breton dit qu'ils pourraient envisager quelques caractéristiques comme " caractéristiques triviales », puis les jeter à la AdaBoost.

En plus, je l'ai écrit versions Python et Matlab de votre code afin que je puisse tester le code moi-même (plus facile à déboguer et à suivre pour moi) et je les poster ici si quelqu'un les trouver quelque temps utile.

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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top