Der Harris Eckendetektor
1988 beschrieben Chris Harris und Mike Stephens einen verbesserten Eckendetektor als Erweiterung des Eckendetektors von Moravec.
Während Moravec die Summe der quadratischen Differenzen
über einem Fenster \(W\) für vier grundlegende Richtungen
betrachtet, erweiteren Harris und Stephens diese Idee. Sie approximieren \(I(x_k + \Delta x, y_k + \Delta y)\) über die s.g. Taylorapproximation ersten Grades, also
und erhalten damit die Approximation
Diese Gleichung läßt sich mit
schreiben als
Dabei nennt man \(M\) Strukturtensor. Harris und Stephens berechnen dann die s.g. Eckenstärke als
mit \(\kappa \approx 0.04\). In diesem Praktikum implementieren wir den Eckendetektor „from scatch“.
Der Code
In diesem Praktikum arbeiten Sie in der Datei
kanten.py
und implementieren die Funktion processImage
Schritt 1: Das Bild in Graustufen umwandeln
Wir müssen zunächst das Bild in Graustufen umwandeln. Konvertieren Sie das Bild mit der cv2.cvtColor Methode. Wandeln Sie das Bild danach über np.float32 in ein Float-Bild um. Normieren Sie die Grauwerte vorher indem Sie durch 255.0 teilen.
Lösung anzeigen
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame_gray = np.float32(frame_gray / 255.0)
Schritt 2: Die Bildgradienten berechnen
Berechnen Sie nun mit der cv2.Sobel Methode wieder die Bildableitungen in X- und Y-Richtung. Verwenden Sie ksize=3 und ddepth=cv2.CV_32F.
Lösung anzeigen
gx = cv2.Sobel(frame, cv2.CV_32F, 1, 0, ksize=3) / 4.0
gy = cv2.Sobel(frame, cv2.CV_32F, 0, 1, ksize=3) / 4.0
Schritt 3: Den Strukturtensor \(M\) vorbereiten
Um den Strukturtensor berechnen zu können berechnen Sie zunächst
und speichern die Ergebnisse in drei neuen Bildern.
Lösung anzeigen
Ix2 = gx ** 2
IxIy = gx * gy
Iy2 = gy ** 2
Schritt 4: Den Strukturtensor berechnen
Der Strukturtensor \(M\) für jeden einzelnen Pixel ergibt sich durch Summation der Bilder \(I_x^2\), \(I_y^2\) sowie \(I_x I_y\). Um dies zu erreichen falten wir diese Bilder mit einem s.g. Block-Kernel
bestehend nur aus einsen. Importieren Sie das scipy Paket und verwenden Sie die convolve2d Methode um diese Faltung durchzuführen. Sie können einen geeigneten Kernel mit np.ones erzeugen. Tip: Dividieren Sie durch die Anzahl einsen in ihrem Kernel um effektiv der Mittelwert anstatt der Summe zu bilden.
Lösung anzeigen
N = 7
Ix2 = signal.convolve2d(Ix2, np.ones((N,N))) / (N**2)
Iy2 = signal.convolve2d(Iy2, np.ones((N,N))) / (N**2)
IxIy = signal.convolve2d(IxIy, np.ones((N,N))) / (N**2)
Schritt 5: Die Eckenstärke berechnen
Um die Eckenstärke zu berechnen betrachten wir zunächst die nochmal Gleichung
mit
Für die Determinante finden wir
und für die Spur finden wir entsprechend
Berechnen Sie nun die Determinante sowie die Spur im Python-Code und berechnen Sie dann die Eckenstärke \(R\) für \(kappa = 0.04\).
Lösung anzeigen
kappa = 0.04
det = Ix2 * Iy2 - IxIy ** 2
trace = Ix2 + Iy2
strength = det - kappa * trace**2
Schritt 6: Die Eckenstärke anzeigen
Die Eckenstärke kann sowohl negativ als auch positiv sein. Wir sind jedoch nur an großen positiven Werten interessiert. Normieren Sie die Eckenstärke, indem Sie durch das globale Maximum dividieren (verwenden Sie np.max).
Nun binarisieren wir das Bild indem wir zunächst ein gleichgroßes Bild erzeugen (z.B. mit np.zeros_like) und überall dort, wo die Eckenstärke größer ist als ein Schwellwert \(T\) eine 1 setzen. Zeigen Sie dann beide Bilder mit cv2.imshow an.
Lösung anzeigen
strength /= np.max(strength)
corners = np.zeros_like(strength)
corners[strength > 0.1] = 1.0
cv2.imshow("Harris Corner Strength", strength)
cv2.imshow("Harris Corners", corners)