Pregunta

He estado implementando una adaptación de Algoritmo de detección de rostros de Viola-Jones.La técnica se basa en colocar un subcuadro de 24x24 píxeles dentro de una imagen y, posteriormente, colocar elementos rectangulares en su interior en todas las posiciones y en todos los tamaños posibles.

Estas entidades pueden constar de dos, tres o cuatro rectángulos.Se presenta el siguiente ejemplo.

Rectangle features

Afirman que el conjunto exhaustivo supera los 180.000 (sección 2):

Dado que la resolución base del detector es 24x24, el conjunto exhaustivo de características del rectángulo es bastante grande, más de 180.000.Tenga en cuenta que, a diferencia de la base de HAAR, el conjunto de características del rectángulo es excesivo.

Las siguientes afirmaciones no se indican explícitamente en el documento, por lo que son suposiciones de mi parte:

  1. Solo hay 2 entidades de dos rectángulos, 2 entidades de tres rectángulos y 1 entidad de cuatro rectángulos.La lógica detrás de esto es que estamos observando la diferencia entre los rectángulos resaltados, no explícitamente el color o la luminancia ni nada por el estilo.
  2. No podemos definir el tipo de característica A como un bloque de 1x1 píxeles;al menos debe tener al menos 1x2 píxeles.Además, el tipo D debe tener al menos 2x2 píxeles y esta regla se aplica de acuerdo con las demás características.
  3. No podemos definir el tipo de característica A como un bloque de 1x3 píxeles ya que el píxel del medio no se puede dividir y restarlo de sí mismo es idéntico a un bloque de 1x2 píxeles;este tipo de característica solo se define para anchos pares.Además, el ancho del elemento tipo C debe ser divisible por 3 y esta regla se aplica de acuerdo con el resto de elementos.
  4. No podemos definir una característica con un ancho y/o alto de 0.Por lo tanto, iteramos X y y a 24 menos el tamaño de la característica.

Con base en estas suposiciones, he contado el conjunto exhaustivo:

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

El resultado es 162,336.

La única forma que encontré para aproximarme a los "más de 180.000" de los que hablan Viola & Jones es descartar la suposición n.° 4 e introducir errores en el código.Esto implica cambiar cuatro líneas respectivamente a:

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

El resultado es entonces 180,625.(Tenga en cuenta que esto evitará efectivamente que las funciones toquen la parte derecha y/o la parte inferior del bastidor auxiliar).

Ahora por supuesto la pregunta:¿Han cometido un error en su implementación?¿Tiene algún sentido considerar entidades con una superficie de cero?¿O lo estoy viendo de forma equivocada?

¿Fue útil?

Solución

A la mirada más cercana, su código es correcto para mí; lo que hace que uno se pregunte si los autores originales tenían un error off-by-one. Creo que alguien debería buscar la forma OpenCV implementa!

Sin embargo, una sugerencia para que sea más fácil de entender es darle la vuelta al orden del de bucles repasando todos los tamaños en primer lugar, a continuación, un bucle sobre las posibles ubicaciones dado el tamaño:

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

con los mismos resultados que el 162336 anterior


Para verificarlo, he probado el caso de una ventana de 4x4 y controlados manualmente todos los casos (fácil contar desde 1x2 / 2x1 y 1x3 / 3x1 formas se hacen girar las mismas sólo 90 grados):

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

Otros consejos

todo.Todavía hay cierta confusión en los artículos de Viola y Jones.

En su artículo CVPR'01 se afirma claramente que

"Más específicamente, utilizamos trestipos de características.El valor de un característica de dos rectángulos es la diferencia entre la suma de los píxeles dentro de dos regiones rectangulares.Las regiones tienen el mismo tamaño y forma y son adyacentes horizontal o verticalmente (ver Figura 1). Una característica de tres rectángulos Calcula la suma dentro de dos rectángulos externos restados de la suma en un rectángulo central.Finalmente una característica de cuatro rectángulos".

En el trabajo del IJCV'04 se dice exactamente lo mismo. En total, 4 características.Pero, por extraño que parezca, esta vez afirmaron que el conjunto completo de funciones es 45396.Esa no parece ser la versión final. Aquí supongo que se introdujeron algunas restricciones adicionales, como min_width, min_height, relación ancho/alto e incluso posición.

Tenga en cuenta que ambos documentos se pueden descargar en su pagina web.

Tener no lee todo el periódico, la redacción de su cotización se pega hacia fuera en mí

  

Dado que la resolución base de la   detector es 24x24, el conjunto exhaustivo   de características rectángulo es bastante grande,   más de 180.000. Tenga en cuenta que a diferencia de la   base Haar, el conjunto de rectángulo   características es sobrecompletos.

"El conjunto de características del rectángulo es sobrecompletos" "Conjunto exhaustivo"

suena a mí como un sistema para arriba, donde espero que el escritor de papel para seguir con una explicación de cómo se entresacan el espacio de búsqueda a un conjunto más efectivo, mediante, por ejemplo, deshacerse de los casos triviales como rectángulos con área de superficie cero.

editar: o el uso de algún tipo de algoritmo de aprendizaje automático, como los consejos abstractos en. conjunto exhaustivo implica todas las posibilidades, no sólo los "razonables".

No hay ninguna garantía de que cualquier autor de cualquier tipo de papel es correcto en todos sus supuestos y conclusiones. Si cree que esa suposición # 4 es válida, a continuación, mantener esa suposición, y probar su teoría. Es posible tener más éxito que los autores originales.

Muy buena observación, pero podría implícitamente cero almohadilla del marco 24x24, o "desbordamiento" y comenzar a usar primeros píxeles cuando se pone fuera de límites, como en turnos rotativos, o como dijo Breton se podría considerar algunas características como " características triviales" y luego tirarlos a la basura con el AdaBoost.

Además, escribí versiones de Python y Matlab de su código para que pueda probar el código mismo (más fácil de depurar y seguir para mí) y por lo que les publicar aquí si alguien los encuentre en algún ú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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top