Good Features To Track
In diesem Praktikum verwenden wir die OpenCV-Funktion cv2.goodFeaturesToTrack, um starke und gut voneinander getrennte Ecken in einem Kamerabild zu finden. Die Funktion baut auf derselben Grundidee wie der Harris-Eckendetektor auf, nimmt uns aber die Berechnung der Eckenstärke, die Schwellwertbildung und die Auswahl lokaler Maxima ab.
Theorie
Für jeden Bildpunkt wird lokal der Strukturtensor
betrachtet. Seine Eigenwerte \(\lambda_1\) und \(\lambda_2\) beschreiben, wie stark sich die Bildintensität in zwei unabhängigen Richtungen ändert.
Ist nur ein Eigenwert groß, liegt typischerweise eine Kante vor.
Sind beide Eigenwerte groß, liegt typischerweise eine Ecke vor.
Sind beide Eigenwerte klein, handelt es sich um eine nahezu konstante Fläche.
Die Funktion cv2.goodFeaturesToTrack kann entweder das Harris-Kriterium
verwenden oder standardmäßig das Shi-Tomasi-Kriterium
nutzen. Danach werden nur Punkte behalten, deren Qualität mindestens qualityLevel mal so groß ist wie die beste gefundene Ecke. Zusätzlich sorgt minDistance dafür, dass die zurückgegebenen Punkte nicht zu dicht beieinander liegen.
Der Code
In diesem Praktikum arbeiten Sie in der Datei
harris/good_features.py
Implementieren Sie zunächst die Funktion processImage. Diese soll ein Kamerabild entgegennehmen, gute Ecken bestimmen und ein neues Bild mit eingezeichneten Markierungen zurückgeben. Anschließend vervollständigen Sie den Haupt-Loop, so dass die Webcam geöffnet und das Ergebnis live angezeigt wird.
Aufgabe 1: Das Bild in Graustufen umwandeln
cv2.goodFeaturesToTrack arbeitet auf einem einkanaligen Bild. Wandeln Sie das Kamerabild deshalb zuerst mit cv2.cvtColor in ein Grauwertbild um.
Lösung anzeigen
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
Aufgabe 2: Gute Ecken finden
Rufen Sie nun cv2.goodFeaturesToTrack mit dem Grauwertbild auf. Verwenden Sie zunächst maximal 100 Ecken, ein qualityLevel von 0.01 und einen Mindestabstand von 10 Pixeln zwischen zwei Ecken.
Die Funktion gibt entweder None zurück, wenn keine passenden Ecken gefunden wurden, oder ein Array der Form \(N \times 1 \times 2\). Die letzte Dimension enthält jeweils die Koordinaten \((x,y)\) einer Ecke.
Lösung anzeigen
corners = cv2.goodFeaturesToTrack(
gray,
maxCorners=100,
qualityLevel=0.01,
minDistance=10,
)
Aufgabe 3: Die gefundenen Ecken einzeichnen
Zeichnen Sie die gefundenen Ecken auf einer Kopie des Kamerabildes ein. Prüfen Sie vorher, ob überhaupt Ecken gefunden wurden. Da OpenCV zum Zeichnen ganze Pixelkoordinaten erwartet, wandeln Sie die Koordinaten mit np.int32 um.
Verwenden Sie anschließend cv2.circle, um jede Ecke als kleinen grünen Kreis zu markieren.
Lösung anzeigen
overlay = frame.copy()
if corners is not None:
corners = np.int32(corners)
for corner in corners:
x, y = corner.ravel()
cv2.circle(overlay, (x, y), 4, (0, 255, 0), -1)
return overlay
Aufgabe 4: Die Webcam öffnen und das Ergebnis anzeigen
Vervollständigen Sie nun den Haupt-Loop in mainLoop. Öffnen Sie die Standardkamera mit cv2.VideoCapture(0), lesen Sie in einer Endlosschleife jeweils ein neues Bild, rufen Sie processImage auf und zeigen Sie das Ergebnis mit cv2.imshow an.
Beenden Sie das Programm, wenn der Benutzer die Escape-Taste drückt. Der zugehörige Tastencode ist 27. Geben Sie am Ende die Kamera wieder frei und schließen Sie alle OpenCV-Fenster.
Lösung anzeigen
cam = cv2.VideoCapture(0)
while True:
_, frame = cam.read()
overlay = processImage(frame)
cv2.imshow("Good Features To Track", overlay)
if cv2.waitKey(1) == 27:
break
cam.release()
cv2.destroyAllWindows()
Experimentieren
Variieren Sie die Parameter von cv2.goodFeaturesToTrack und beobachten Sie das Ergebnis:
Erhöhen Sie maxCorners, um mehr mögliche Ecken zuzulassen.
Erhöhen Sie qualityLevel, um nur sehr starke Ecken zu behalten.
Erhöhen Sie minDistance, um die gefundenen Ecken weiter auseinander zu halten.
Setzen Sie useHarrisDetector=True, um statt des Shi-Tomasi-Kriteriums das Harris-Kriterium zu verwenden.