Rectangle Detection / Tracking mit OpenCV

9

Was ich brauche

Ich arbeite gerade an einem Augmented-Reality-Spiel. Der Controller, den das Spiel verwendet (ich spreche hier über das physische Eingabegerät), ist ein monofarbiges, rechteckiges Papierstück. Ich muss die Position, Drehung und Größe dieses Rechtecks ​​im Aufnahmestrom der Kamera erkennen. Die Erkennung sollte für die Skalierung invariant und für die Drehung entlang der X- und Y-Achse invariant sein.

Die Skalierungsinvarianz wird benötigt, falls der Benutzer das Papier weg oder in Richtung der Kamera bewegt. Ich muss den Abstand des Rechtecks ​​nicht kennen, damit die Skaleninvarianz in Größeninvarianz umwandelt.

Die Rotationsinvarianz wird benötigt, wenn der Benutzer das Rechteck entlang seiner lokalen X- und / oder Y-Achse neigt. Eine solche Drehung verändert die Form des Papiers von Rechteck zu Trapez. In diesem Fall kann die objektorientierte Begrenzungsbox verwendet werden, um die Größe des Papiers zu messen.

Was ich getan habe

Zu Beginn gibt es einen Kalibrierungsschritt. Ein Fenster zeigt den Kamera-Feed und der Benutzer muss auf das Rechteck klicken. Beim Klicken wird die Farbe des Pixels, auf das die Maus zeigt, als Referenzfarbe verwendet. Die Rahmen werden in einen HSV-Farbraum umgewandelt, um die Farbunterscheidung zu verbessern. Ich habe 6 Schieberegler, die die oberen und unteren Schwellenwerte für jeden Kanal einstellen. Diese Schwellenwerte werden verwendet, um das Bild zu digitalisieren (mit der Funktion inRange von opencv).
Danach erodiere und dehne ich das Binärbild, um Rauschen zu entfernen und Nerby-Chunks zu vereinen (mit den Funktionen erode und dilate von opencv).
Der nächste Schritt ist das Auffinden von Konturen (mit der Funktion findContours von opencv) im Binärbild. Diese Konturen werden verwendet, um die kleinsten orientierten Rechtecke zu erkennen (mit Hilfe der Funktion minAreaRect von opencv). Als Endergebnis verwende ich das Rechteck mit der größten Fläche.

Ein kurzer Abschluss des Verfahrens:

  1. Nimm einen Rahmen
  2. Konvertiere diesen Frame in HSV
  3. Binarisieren Sie es (mit der vom Benutzer ausgewählten Farbe und den Schwellenwerten der Schieberegler)
  4. Wenden Sie morph ops (erodieren und erweitern) an
  5. Finde Konturen
  6. Holen Sie sich die kleinste orientierte Bouding-Box jeder Kontur
  7. Nimm den größten dieser Begrenzungsrahmen als Ergebnis

Wie Sie vielleicht bemerkt haben, mache ich keinen Vorteil aus dem Wissen über die tatsächliche Form des Papiers, einfach weil ich nicht weiß, wie man diese Informationen richtig benutzt.

Ich habe auch über die Tracking-Algorithmen von opencv nachgedacht. Aber es gab drei Gründe, die mich daran hinderten, sie zu benutzen:

  1. Scale-Invarianz: Soweit ich über einige der Algorithmen gelesen habe, unterstützen einige verschiedene Skalen des Objekts nicht.
  2. Bewegungsvorhersage: Einige Algorithmen verwenden Bewegungsvorhersage für bessere Leistung, aber das Objekt, das ich tracking bewegt sich völlig zufällig und daher unvorhersehbar.
  3. Einfachheit: Ich suche nur nach einem monofarbigen Rechteck in einem Bild, nichts Besonderes wie Auto oder Personentracking.

Hier ist ein - relativ - guter Fang (Binärbild nach erodieren und erweitern)

und hier ist ein schlechter

Die Frage

Wie kann ich die Erkennung im Allgemeinen verbessern und insbesondere widerstandsfähiger gegenüber Lichtveränderungen sein?

Aktualisieren

Hier sind einige rohe Bilder zum Testen.

Können Sie nicht dickeres Material verwenden?
Ja, ich kann und ich schon (leider kann ich im Moment nicht auf diese Stücke zugreifen). Das Problem bleibt jedoch bestehen. Auch wenn ich Material wie Karton verwende. Es ist nicht so leicht wie Papier gebogen, aber man kann es immer noch biegen.

Wie erhalten Sie die Größe, Drehung und Position des Rechtecks?
Die Funktion minAreaRect von opencv gibt ein Objekt RotatedRect zurück. Dieses Objekt enthält alle Daten, die ich brauche.

Hinweis
Da das Rechteck einfarbig ist, besteht keine Möglichkeit, zwischen oben und unten oder links und rechts zu unterscheiden. Dies bedeutet, dass die Rotation immer im Bereich [0, 180] liegt, was für meine Zwecke völlig in Ordnung ist. Das Verhältnis der beiden Seiten des Rect ist immer w:h > 2:1 . Wenn das Rechteck ein Quadrat wäre, würde sich der Bereich von roation in [0, 90] ändern, aber dies kann hier als irrelevant angesehen werden.

Wie in den Kommentaren vorgeschlagen, werde ich versuchen, Histogramm-Entzerrung durchzuführen, um Helligkeitsprobleme zu reduzieren und einen Blick auf ORB, SURF und SIFT zu werfen.

Ich werde den Fortschritt aktualisieren.

    
Timo 13.06.2017, 12:47
quelle

2 Antworten

1

Ich weiß, dass es eine Weile her ist, seit ich die Frage gestellt habe. Ich habe kürzlich das Thema weiter verfolgt und mein Problem gelöst (allerdings nicht durch die Rechteckerkennung).

Änderungen

  • Verwenden von Holz, um meine Controller (die "Rechtecke") wie unten zu stärken.
  • Platzierte 2 ArUco Markierungen auf jedem Controller.

Wie es funktioniert

  • Konvertieren Sie den Rahmen in Graustufen,
  • Downsample es (um die Leistung während der Erkennung zu erhöhen),
  • Entzerren Sie das Histogramm mit cv::equalizeHist ,
  • finde Marker mit cv::aruco::detectMarkers ,
  • korrelieren Marker (wenn mehrere Controller),
  • Analysiere Marker (Position und Rotation),
  • berechnen Sie das Ergebnis und wenden Sie eine Fehlerkorrektur an.

Es stellte sich heraus, dass die Marker-Erkennung sehr robust gegenüber Veränderungen der Beleuchtung und unterschiedlichen Betrachtungswinkeln ist, was es mir erlaubt, alle Kalibrierungsschritte zu überspringen.

Ich habe zwei Marker auf jedem Controller platziert, um die Erkennungsrobustheit noch mehr zu erhöhen. Beide Marker müssen nur einmal detektiert werden (um zu messen, wie sie korrelieren). Danach ist es ausreichend, nur einen Marker pro Controller zu finden, da der andere aus der zuvor berechneten Korrelation extrapoliert werden kann.

Hier ist ein Erkennungsergebnis in einer hellen Umgebung:

in einer dunkleren Umgebung:

und beim Ausblenden eines der Marker (der blaue Punkt zeigt die extrapolierte Markerposition an):

Fehler

Die anfängliche Formerkennung, die ich implementiert habe, hat nicht gut funktioniert. Es war sehr anfällig für Änderungen der Beleuchtung. Außerdem war ein erster Kalibrierungsschritt erforderlich.

Nach dem Shape-Detection-Ansatz habe ich SIFT und ORB in Kombination mit Brute Force und Knn Matcher ausprobiert, um Features in den Frames zu extrahieren und zu lokalisieren. Es stellte sich heraus, dass monochrome Objekte nicht viele Schlüsselpunkte bieten (was für eine Überraschung). Die Performance von SIFT war trotzdem schrecklich (ca. 10 fps @ 540p). Ich zeichnete einige Linien und andere Formen auf dem Controller, was dazu führte, dass mehr Keypoints zur Verfügung standen. Dies führte jedoch nicht zu großen Verbesserungen.

    
Timo 19.01.2018, 23:18
quelle
2

Der H-Kanal im HSV-Raum ist der Farbton, und er ist nicht empfindlich gegenüber Lichtveränderungen. Roter Bereich in etwa [150.180].

Basierend auf den genannten Informationen mache ich folgende Arbeiten.

  1. Wechseln Sie in den HSV-Bereich, teilen Sie den H-Kanal und den Schwellenwert und normalisieren Sie ihn.
  2. Wende morph ops (offen) an
  3. Finden Sie Konturen, filtern Sie nach bestimmten Eigenschaften (Breite, Höhe, Fläche, Verhältnis usw.).

PS. Ich kann das hochgeladene Bild aufgrund des NETZWERKS nicht in der Dropbox abrufen. Also verwende ich einfach die rechte Seite deines zweiten Bildes als Eingabe.

%Vor%

Nun erhalten wir das Ergebnis als (h, normiert, geöffnet):

Finde dann Konturen und filtere sie.

%Vor%

Das Ergebnis ist wie folgt:

%Vor%

Da sich das blaue Rechteck im Quellbild befindet, ist die Karte in zwei Seiten aufgeteilt. Aber ein sauberes Bild wird kein Problem haben.

    
Silencer 03.10.2017 20:41
quelle