black_grayscale_line_following.py
# Dieses Werk ist unter der MIT-Lizenz lizenziert.
# Copyright (c) 2013-2023 OpenMV LLC. Alle Rechte vorbehalten.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Beispiel für Linienverfolgung mit schwarzer Graustufenlinie
#
# Der Bau eines linienfolgenden Roboters erfordert erheblichen Aufwand. Dieses Beispielskript
# zeigt, wie der Bildverarbeitungsteil des linienfolgenden Roboters umgesetzt wird. Sie
# können die Ausgabe dieses Skripts verwenden, um einen Roboter mit Differentialantrieb dazu zu bringen,
# einer Linie zu folgen. Dieses Skript erzeugt lediglich einen einzelnen Lenkwert, der
# Ihrem Roboter mitteilt, nach links oder rechts zu fahren.
#
# Damit dieses Skript ordnungsgemäß funktioniert, sollten Sie die Kamera in einem
# Winkel von etwa 45 Grad auf eine Linie richten. Bitte stellen Sie sicher, dass sich nur die Linie im
# Sichtfeld der Kamera befindet.
import csi
import time
import math
# Verfolgt eine schwarze Linie. Verwenden Sie [(128, 255)] zum Verfolgen einer weißen Linie.
GRAYSCALE_THRESHOLD = [(0, 64)]
# Jede ROI ist (x, y, w, h). Der Linienerkennungsalgorithmus versucht, den
# Schwerpunkt des größten Blobs in jeder ROI zu finden. Die x-Position der Schwerpunkte
# wird dann mit unterschiedlichen Gewichtungen gemittelt, wobei der größte Gewichtungswert
# der ROI nahe dem unteren Bildrand zugewiesen wird und ein geringerer der nächsten ROI usw.
ROIS = [ # [ROI, Gewichtung]
(0, 100, 160, 20, 0.7), # Sie müssen die Gewichtungen für Ihre Anwendung anpassen
(0, 50, 160, 20, 0.3), # je nachdem, wie Ihr Roboter aufgebaut ist.
(0, 0, 160, 20, 0.1),
]
# Den Gewichtungsdivisor berechnen (damit die Gewichtungen nicht manuell zu 1 addiert werden müssen).
weight_sum = 0
for r in ROIS:
weight_sum += r[4] # r[4] ist die ROI-Gewichtung.
# Kamera-Einrichtung...
csi0 = csi.CSI()
csi0.reset() # Kamerasensor initialisieren.
csi0.pixformat(csi.GRAYSCALE) # Graustufen verwenden.
csi0.framesize(csi.QQVGA) # QQVGA für Geschwindigkeit verwenden.
csi0.snapshot(time=2000) # Neue Einstellungen wirksam werden lassen.
csi0.auto_gain(False) # muss für das Farb-Tracking deaktiviert werden
csi0.auto_whitebal(False) # muss für das Farb-Tracking deaktiviert werden
clock = time.clock() # Verfolgt die FPS.
while True:
clock.tick() # Erfasst die vergangenen Millisekunden zwischen den Aufrufen von snapshots().
img = csi0.snapshot() # Nimmt ein Bild auf und gibt es zurück.
centroid_sum = 0
for r in ROIS:
blobs = img.find_blobs(
GRAYSCALE_THRESHOLD, roi=r[0:4], merge=True
) # r[0:4] ist das ROI-Tupel.
if blobs:
# Den Blob mit den meisten Pixeln finden.
largest_blob = max(blobs, key=lambda b: b.pixels)
# Ein Rechteck um den Blob zeichnen.
img.draw_detection(largest_blob)
centroid_sum += largest_blob.cx * r[4] # r[4] ist die ROI-Gewichtung.
center_pos = centroid_sum / weight_sum # Den Mittelpunkt der Linie bestimmen.
# Die center_pos in einen Ablenkwinkel umwandeln. Wir verwenden eine nichtlineare
# Operation, damit die Reaktion umso stärker wird, je weiter wir von der Linie
# entfernt sind. Nichtlineare Operationen eignen sich gut, um bei der Ausgabe solcher Algorithmen
# einen „Trigger“-artigen Reaktionseffekt zu erzeugen.
deflection_angle = 0
# Die 80 stammt von der halben X-Auflösung, die 60 von der halben Y-Auflösung. Die
# folgende Gleichung berechnet lediglich den Winkel eines Dreiecks, bei dem
# die Gegenkathete des Dreiecks die Abweichung der Mittelposition
# von der Mitte ist und die Ankathete der halben Y-Auflösung entspricht. Dies begrenzt
# die Winkelausgabe auf etwa -45 bis 45. (Es ist nicht ganz -45 und 45).
deflection_angle = -math.atan((center_pos - 80) / 60)
# Winkel von Radiant in Grad umrechnen.
deflection_angle = math.degrees(deflection_angle)
# Jetzt haben Sie einen Winkel, der angibt, wie stark der Roboter gelenkt werden soll, der
# den Teil der Linie in Roboternähe sowie Teile
# der weiter entfernten Linie für eine bessere Vorhersage einbezieht.
print("Turn Angle: %f" % deflection_angle)
print(clock.fps()) # Hinweis: Ihre OpenMV Cam läuft etwa halb so schnell, während
# sie mit Ihrem Computer verbunden ist. Die FPS sollten sich erhöhen, sobald die Verbindung getrennt wird.