Ich habe eine Anpassung des Gesichtserkennungsalgorithmus von Viola-Jones implementiert . Die Technik beruht darauf, dass ein Teilrahmen mit 24 x 24 Pixeln in einem Bild platziert wird und anschließend rechteckige Merkmale an jeder Position mit jeder möglichen Größe darin platziert werden.
Diese Features können aus zwei, drei oder vier Rechtecken bestehen. Das folgende Beispiel wird vorgestellt.
Sie behaupten, dass der vollständige Satz mehr als 180.000 beträgt (Abschnitt 2):
Angesichts der Grundauflösung des Detektors von 24 x 24 ist der erschöpfende Satz von Rechteckmerkmalen mit über 180.000 recht groß. Beachten Sie, dass im Gegensatz zur Haar-Basis der Satz von Rechteckmerkmalen übervollständig ist.
Die folgenden Aussagen werden in dem Papier nicht explizit angegeben, daher handelt es sich um Annahmen meinerseits:
- Es gibt nur 2 Zwei-Rechteck-Features, 2 Drei-Rechteck-Features und 1 Vier-Rechteck-Feature. Die Logik dahinter ist, dass wir den Unterschied zwischen den hervorgehobenen Rechtecken beobachten, nicht explizit die Farbe oder Luminanz oder irgendetwas in dieser Art.
- Wir können den Feature-Typ A nicht als 1x1-Pixelblock definieren. Es muss mindestens 1x2 Pixel betragen. Außerdem muss Typ D mindestens 2 x 2 Pixel groß sein, und diese Regel gilt entsprechend für die anderen Merkmale.
- Wir können den Merkmalstyp A nicht als 1x3-Pixelblock definieren, da das mittlere Pixel nicht partitioniert werden kann und das Subtrahieren von sich selbst mit einem 1x2-Pixelblock identisch ist. Dieser Feature-Typ ist nur für gerade Breiten definiert. Außerdem muss die Breite des Merkmalstyps C durch 3 teilbar sein, und diese Regel gilt entsprechend für die anderen Merkmale.
- Wir können kein Feature mit einer Breite und / oder Höhe von 0 definieren. Daher iterieren wir x und y bis 24 abzüglich der Größe des Features.
Basierend auf diesen Annahmen habe ich die erschöpfende Menge gezählt:
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++;
}
}
}
}
}
Das Ergebnis ist 162.336 .
Der einzige Weg, den ich gefunden habe, um die "über 180.000", von denen Viola & Jones sprechen, zu approximieren, besteht darin, die Annahme Nr. 4 fallen zu lassen und Fehler in den Code einzuführen. Dies beinhaltet das Ändern von vier Zeilen in:
for (int width = 0; width < frameSize-x; width+=sizeX)
for (int height = 0; height < frameSize-y; height+=sizeY)
Das Ergebnis ist dann 180.625 . (Beachten Sie, dass dadurch effektiv verhindert wird, dass die Features jemals die rechte und / oder untere Seite des Hilfsrahmens berühren.)
Nun natürlich die Frage: Haben sie einen Fehler bei ihrer Implementierung gemacht? Ist es sinnvoll, Features mit einer Oberfläche von Null zu berücksichtigen? Oder sehe ich das falsch?