Haben Konturen, die von cv :: findContours zurückgegeben werden, eine konsistente Ausrichtung?

8

Ich benutze OpenCVs cv::findContours Funktion, um Konturen in a zu extrahieren binäre Bild, insbesondere extrahiere ich eine Hierarchie von Konturen (mit dem CV_RETR_CCOMP -Flag). Irgendwann bei meiner weiteren Verarbeitung dieser Konturen muss ich auf eine konsistente Vertex-Ausrichtung dieser Konturen (d. H. Gegen den Uhrzeigersinn vs. im Uhrzeigersinn) setzen.

Natürlich kann ich diese Orientierung selbst bestimmen, indem ich das Vorzeichen des Konturbereichs verwende (wie von cv::contourArea(..., true) ), aber ich frage mich, ob das überhaupt nötig ist (außerdem funktioniert es nicht einmal für Konturen mit einer Fläche von 0, dh dünne Linien im Quellbild) oder wenn cv::findContours garantiert bereits eine konsistente Orientierung für die generierten Konturen. Ich habe einige der generierten Konturen überprüft, und cv::contourArea ist tatsächlich scheint , um negative Werte für äußere Konturen und positive Werte für innere Konturen zurückzugeben. Allerdings konnte ich in der OpenCV-Dokumentation keine tatsächliche Garantie finden.

Also, ist es spezifisch garantiert , dass die von cv::findContours zurückgegebenen Konturen immer eine konsistente Ausrichtung haben? Ist dies irgendwo dokumentiert? Oder ist es von Version zu Version (meine ist 2.4.5 für diese Angelegenheit)? Schlagen die tatsächlichen Ausführungen zum Algorithmus, auf den in der Dokumentation verwiesen wird , bereits etwas dazu vor ? Oder kann jemand mit ein wenig mehr Einblick in die tatsächliche Implementierung von OpenCV etwas mehr dazu sagen als die Schnittstellendokumentation?

    
Christian Rau 26.07.2017, 09:58
quelle

2 Antworten

4

Die von cv:findContours zurückgegebenen Konturen sollten konsistent ausgerichtet sein. Die äußeren Konturen sollten gegen den Uhrzeigersinn, die inneren Konturen im Uhrzeigersinn ausgerichtet sein. Dies folgt direkt aus dem Algorithmus, der in Anhang 1 von Suzukis und Abes Papier beschrieben ist.

Das Bild wird zeilenweise von oben links nach unten rechts abgetastet. Wenn ein zu einer Grenze gehörendes Pixel gefunden wird, folgt auf die Grenze die Betrachtung der Nachbarn des ersten Pixels entgegen dem Uhrzeigersinn (siehe Schritt 3.3 im Algorithmus), bis ein Nicht-Hintergrund-Pixel gefunden wird. Dies wird zur Kontur hinzugefügt und die Suche wird von diesem Pixel fortgesetzt.

Wichtig ist, dass in der ersten Iteration der zuerst betrachtete Nachbar davon abhängt, ob es sich um eine innere oder eine äußere Grenze handelt. Bei einer äußeren Grenze wird zuerst der rechte Nachbar besucht; im Falle einer inneren Grenze ist es der linke Nachbar. Im nächsten Suchschritt beginnt die Suche mit dem zuletzt besuchten Pixel.

Aufgrund des Scannens von oben links nach rechts unten ist bei der Erkennung eines äußeren Rahmens sichergestellt, dass alle benachbarten Pixel links und oben im Rahmen des Randpixels Hintergrundpixel sind. Bei der inneren Grenze ist es genau umgekehrt, alle Nachbarn links und oben sind Nicht-Hintergrund-Pixel.

In Kombination mit den verschiedenen Startpositionen für den Besuch der benachbarten Pixel ergibt sich eine vorhersagbare Orientierung der Konturen.

Dieser Algorithmus ist in der Funktion icvFetchContour Dies wird intern von cv:findContour verwendet. Von dort wird klar, dass die Pixel dem Konturpolygon in der Reihenfolge hinzugefügt werden, in der sie besucht werden.

Wie die Dokumentation für cv::findContours ausdrücklich besagt, dass sie die Algorithmus von Suzuki et al. und da in diesem Papier die Richtung und Reihenfolge für den Besuch der Pixel explizit definiert ist, kann man meiner Meinung nach davon ausgehen, dass die Ausrichtung irgendwie garantiert ist.

    
Christoph Böhme 04.08.2017, 20:59
quelle
3

Ich glaube, Schritt 1 und 4 der Anhang I (in der [Suzuki85] Arbeit, auf die Sie verwiesen haben," Strukturelle Analyse von digitalisierten binären Bildern durch Border Following ") decken Sie Ihre Frage wie folgt ab:

(1) Wählen Sie eine der folgenden Optionen aus:
(a) Wenn f i, j = 1 und f i, j - 1 = 0, dann beschlüsse, dass das Pixel (i, j) die Grenze ist, die auf Anfangspunkt einer äußeren Grenze, NBD-Inkrement und (i 1 , j 1 ) + (i, j - 1).
< em> (b) ...

(2) Abhängig von den Typen der neu gefundenen Grenze und ...

(3) Folgen Sie vom Startpunkt (i, j) aus dem erkannten Rahmen ...

(4) Wenn f i, j <= 1, dann ist LNBD = | f i, j | und setze die Rasterabtastung von dem Pixel (i, j + 1) fort. Der Algorithmus wird beendet, wenn der Scan die untere rechte Ecke des Bildes erreicht.

    
py_guy 04.08.2017 12:57
quelle

Tags und Links