Merkmalspunkte und Deskriptoren
ORB, SIFT und Matching: wie zwei Bilder desselben Gegenstands einander zugeordnet werden, auch wenn sie gedreht, skaliert oder anders beleuchtet sind.
Die Idee
Um zwei Fotos desselben Regals einander zuzuordnen, sucht man markante Stellen: Ecken, Beschriftungen, Kanten von Kartons. Eine glatte weiße Wand hilft nicht, weil jede Stelle darauf gleich aussieht.
Genau das macht ein Merkmalsdetektor: er findet unverwechselbare Punkte und beschreibt ihre Umgebung in einer Zahlenreihe.
Wozu es gut ist
- Panoramen zusammensetzen.
- Ein Etikett auf einem Regalfoto wiederfinden.
- Ein schräg fotografiertes Dokument geradeziehen.
- Bewegung zwischen zwei Videobildern bestimmen.
Zwei Bilder ausrichten
import cv2, numpy as np
a = cv2.imread("vorlage.jpg", cv2.IMREAD_GRAYSCALE)
b = cv2.imread("foto.jpg", cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create(nfeatures=3000)
ka, da = orb.detectAndCompute(a, None)
kb, db = orb.detectAndCompute(b, None)
# ORB liefert Binaerdeskriptoren -> Hamming-Abstand, nicht euklidisch.
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
paare = matcher.knnMatch(da, db, k=2)
# Lowe-Ratio: ein Treffer zaehlt nur, wenn er deutlich besser ist
# als der zweitbeste. Das entfernt die meisten Fehlzuordnungen.
gut = [m for m, n in paare if m.distance < 0.75 * n.distance]
print(f"{len(gut)} von {len(paare)} Zuordnungen behalten")
if len(gut) >= 8:
pa = np.float32([ka[m.queryIdx].pt for m in gut]).reshape(-1, 1, 2)
pb = np.float32([kb[m.trainIdx].pt for m in gut]).reshape(-1, 1, 2)
H, maske = cv2.findHomography(pb, pa, cv2.RANSAC, 5.0)
print("Inlier:", int(maske.sum()), "von", len(gut))
ausgerichtet = cv2.warpPerspective(b, H, (a.shape[1], a.shape[0]))Die Detektoren im Vergleich
| Detektor | Deskriptor | Geschwindigkeit | Robust gegen Skalierung |
|---|---|---|---|
| ORB | binär, 256 Bit | sehr hoch | mittel |
| SIFT | 128 Gleitkommawerte | niedrig | hoch |
| AKAZE | binär | hoch | hoch |
| Shi-Tomasi | keiner, nur Punkte | sehr hoch | keine |
Die Ecke als mathematisches Kriterium
Warum die Ratio funktioniert
Bei einem echten Treffer ist der beste Abstand deutlich kleiner als der zweitbeste, weil es nur eine korrekte Entsprechung gibt. Bei einem falschen Treffer sind beste und zweitbeste Übereinstimmung beide zufällig und damit ähnlich weit entfernt. Ein Verhältnis unter 0,75 filtert empirisch rund 90 Prozent der Fehlzuordnungen bei einem Verlust von etwa 5 Prozent der richtigen.
RANSAC, quantifiziert
Durchgerechnet: bei w = 0,5, s = 4 und p = 0,99 sind
N = log(0,01)/log(1 − 0,0625) = 71 Versuche nötig. Bei w = 0,2 steigt das auf
N = 2876. Der Aufwand wächst also dramatisch mit dem Anteil falscher
Zuordnungen, was erklärt, warum eine gute Vorfilterung mit der Lowe-Ratio
wichtiger ist als eine hohe Iterationszahl.
Anwendung: Regalabgleich
Ein praktischer Ablauf für den Abgleich eines Regalfotos gegen ein Planogramm:
- Vorlage und Foto auf gleiche Größenordnung skalieren, sonst finden zu wenige Punkte zueinander.
- ORB mit 3.000 bis 5.000 Punkten, mehr bringt selten etwas.
- Lowe-Ratio bei 0,7 bis 0,8, strenger bei sich wiederholenden Mustern.
- Homographie nur akzeptieren, wenn mindestens 20 Inlier vorliegen und die Determinante plausibel ist.
- Danach entzerren und erst dann die eigentliche Prüfung durchführen.
Passende Kurse und Quellen
OpenCV-Tutorials
Die offiziellen Anleitungen zu Filtern, Kanten, Merkmalen und Kalibrierung, jeweils mit lauffähigem Python-Code.
Für alle, die Bildverarbeitung selbst schreiben; jedes Beispiel ist lauffähig.