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

\[\begin{split}M = \sum_{(x_k,y_k)\in W} \begin{pmatrix} I_x^2 & I_x I_y\\ I_x I_y & I_y^2 \end{pmatrix}\end{split}\]

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

\[R = det(M) - \kappa \cdot tr(M)^2\]

verwenden oder standardmäßig das Shi-Tomasi-Kriterium

\[R = \min(\lambda_1, \lambda_2)\]

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.

Good Features To Track - Musterlösung

Good Features To Track - Musterlösung