Pergunta

Eu tenho vindo a implementar uma adaptação do rosto Viola-Jones' detecção algoritmo . A técnica baseia-se colocando um subframe de 24x24 pixels dentro de uma imagem, e, posteriormente, colocando características retangulares dentro dele em todas as posições com cada tamanho possível.

Estas características podem consistir de dois, três ou quatro retângulos. O exemplo a seguir é apresentado.

Retângulo apresenta

Eles reivindicam o conjunto exaustivo é mais do que 180k (ponto 2):

Uma vez que a resolução base do detector é 24x24, o conjunto exaustivo de recursos retângulo é bastante grande, mais de 180.000. Note-se que ao contrário da base Haar, o conjunto de retângulo apresenta é overcomplete.

As seguintes declarações são não explicitamente declarado no papel, por isso são hipóteses da minha parte:

  1. Existem apenas 2 características de dois retângulo, 2 apresenta três retângulo e um recurso de quatro retângulo. A lógica por trás disso é que estamos observando o diferença entre os retângulos em destaque, não explicitamente a cor ou luminosidade ou qualquer coisa desse tipo.
  2. Não podemos definir o tipo de recurso Um como um bloco de 1x1 pixel; ele deve pelo menos ser pelo menos pixels 1x2. Além disso, tipo D deve ter pelo menos pixels 2x2, e esta regra segura de acordo com as outras características.
  3. não pode definir o tipo de elemento A, tal como um bloco de pixels 1x3 como o pixel do meio não pode ser particionado, e o subtrair de si é idêntico ao de um bloco de pixels 1x2; este tipo de recurso só é definida para o mesmo larguras. Além disso, a largura do tipo de recurso C deve ser divisível por 3, e esta regra segura de acordo com as outras características.
  4. Não podemos definir uma característica com uma largura e / ou altura de 0. Portanto, iterate x e y e 24 menos o tamanho do recurso.

Com base nesses pressupostos, eu contei o conjunto exaustivo:

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

O resultado é 162.336 .

A única maneira que eu encontrei para aproximar a "mais de 180.000" Viola & Jones falar, está caindo suposição # 4 e através da introdução de erros no código. Isso envolve a alteração quatro linhas, respectivamente:

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

O resultado é então 180.625 . (Note que isto irá prevenir eficazmente as características de nunca tocar o direito e / ou inferior do chassi auxiliar.)

Agora, naturalmente, a pergunta: tem que cometeu um erro na sua implementação? Faz algum sentido considerar características com uma superfície igual a zero? Ou eu estou vendo o caminho errado?

Foi útil?

Solução

Ao olhar mais de perto, o seu código parece correto para mim; que faz uma maravilha se os autores originais tinham um bug off-por-um. Eu acho que alguém deve olhar como implementos OpenCV-lo!

No entanto, uma sugestão para torná-lo mais fácil de entender é inverter a ordem do para laços passando por cima todos os tamanhos primeiros, então looping sobre os locais possíveis, dado o tamanho:

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

com os mesmos resultados que o 162336 anterior


Para verificar isso, eu testei o caso de uma janela 4x4 e manualmente verificado todos os casos (fácil contar desde 1x2 / 2x1 e 1x3 / 3x1 formas são as mesmas apenas 90 graus girado):

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

Outras dicas

todos. Há ainda alguma confusão nos papéis Viola e Jones'.

Em seu artigo CVPR'01 afirma-se claramente que

"Mais especificamente, nós usamos três tipos de recursos. O valor de uma recurso de dois retângulo é a diferença entre a soma do pixels dentro de duas regiões retangulares. As regiões têm o mesmo tamanho e moldar e são horizontalmente ou verticalmente adjacentes (ver Figura 1). Uma característica de três retângulo calcula a soma dentro de dois fora retângulos subtraída da soma um retângulo centro. Finalmente a recurso de quatro retângulo ".

No papel IJCV'04, exatamente a mesma coisa é dita. Assim, no total, 4 recursos . Mas, curiosamente, afirmaram desta vez que o conjunto do recurso exaustiva é 45396! Isso não parece ser a final version.Here Eu acho que algumas restrições adicionais foram introduzidos lá, como MIN_WIDTH, MIN_HEIGHT, largura / taxa de altura e posição mesmo.

Note que ambos os documentos estão disponíveis para download no sua webpage .

Tendo não ler todo o documento, o texto de suas varas cotação para fora em mim

Uma vez que a resolução base do detector é 24x24, o conjunto exaustiva de recursos retângulo é bastante grande, mais de 180.000. Note-se que, ao contrário do base Haar, o conjunto de retângulo apresenta é overcomplete.

"O conjunto de recursos do retângulo é overcomplete" "Conjunto exaustivo"

que soa para mim como um conjunto para cima, onde eu esperar o escritor papel de acompanhar com uma explicação de como eles abater o espaço de busca para baixo para um conjunto mais eficaz, através de, por exemplo, se livrar de casos triviais, como retângulos com área de superfície zero.

edit: ou usando algum tipo de algoritmo de aprendizagem de máquina, como as dicas abstratas no. conjunto exaustivo implica todas as possibilidades, não apenas "razoável" queridos.

Não há garantia de que qualquer autor de qualquer papel está correta em todas as suas suposições e conclusões. Se você acha que essa suposição # 4 é válido, em seguida, manter essa suposição, e experimentar a sua teoria. Você pode ser mais bem sucedidos do que os autores originais.

Muito boa observação, mas eles podem implicitamente zero pad do quadro 24x24, ou "overflow" e começar a usar primeiras pixels quando fica fora dos limites, como em turnos rotativos, ou como disse Breton eles podem considerar algumas características como " trivial apresenta" e depois descartá-las com o AdaBoost.

Além disso, eu escrevi versões Python e Matlab do seu código para que eu possa testar o código me (mais fácil de depurar e siga para mim) e então eu publicá-las aqui, se alguém encontrá-los em algum momento útil.

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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top