black_grayscale_line_following.py
# Questo lavoro è concesso in licenza MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Tutti i diritti riservati.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Esempio di inseguimento di linea nera in scala di grigi
#
# Realizzare un robot che segue linee richiede molto impegno. Questo script di esempio
# mostra come realizzare la parte di visione artificiale del robot che segue linee. È
# possibile usare l'output di questo script per guidare un robot a trazione differenziale a
# seguire una linea. Questo script genera semplicemente un singolo valore di svolta che indica
# al robot di andare a sinistra o a destra.
#
# Perché questo script funzioni correttamente, la fotocamera dovrebbe essere puntata su una linea con
# un'angolazione di circa 45 gradi. Assicurarsi che solo la linea sia all'interno del
# campo visivo della fotocamera.
import csi
import time
import math
# Traccia una linea nera. Usare [(128, 255)] per tracciare una linea bianca.
GRAYSCALE_THRESHOLD = [(0, 64)]
# Ogni roi è (x, y, w, h). L'algoritmo di rilevamento delle linee cercherà di trovare
# il centroide del blob più grande in ciascuna roi. La posizione x dei centroidi
# verrà quindi mediata con pesi diversi, dove il peso maggiore viene assegnato
# alla roi vicino alla parte inferiore dell'immagine e un peso minore alla roi successiva, e così via.
ROIS = [ # [ROI, weight]
(0, 100, 160, 20, 0.7), # Sarà necessario regolare i pesi per la propria applicazione
(0, 50, 160, 20, 0.3), # a seconda di come è configurato il robot.
(0, 0, 160, 20, 0.1),
]
# Calcolare il divisore del peso (lo calcoliamo così non è necessario che i pesi sommino a 1).
weight_sum = 0
for r in ROIS:
weight_sum += r[4] # r[4] è il peso della roi.
# Configurazione della fotocamera...
csi0 = csi.CSI()
csi0.reset() # Inizializza il sensore della fotocamera.
csi0.pixformat(csi.GRAYSCALE) # usare la scala di grigi.
csi0.framesize(csi.QQVGA) # usare QQVGA per la velocità.
csi0.snapshot(time=2000) # Lasciare che le nuove impostazioni abbiano effetto.
csi0.auto_gain(False) # deve essere disattivato per il tracciamento del colore
csi0.auto_whitebal(False) # deve essere disattivato per il tracciamento del colore
clock = time.clock() # Traccia gli FPS.
while True:
clock.tick() # Traccia i millisecondi trascorsi tra le chiamate a snapshot().
img = csi0.snapshot() # Scatta una foto e restituisce l'immagine.
centroid_sum = 0
for r in ROIS:
blobs = img.find_blobs(
GRAYSCALE_THRESHOLD, roi=r[0:4], merge=True
) # r[0:4] è la tupla della roi.
if blobs:
# Trovare il blob con il maggior numero di pixel.
largest_blob = max(blobs, key=lambda b: b.pixels)
# Disegnare un rettangolo intorno al blob.
img.draw_detection(largest_blob)
centroid_sum += largest_blob.cx * r[4] # r[4] è il peso della roi.
center_pos = centroid_sum / weight_sum # Determinare il centro della linea.
# Convertire center_pos in un angolo di deflessione. Stiamo usando un'operazione
# non lineare in modo che la risposta diventi più forte quanto più ci si allontana dalla linea
# in cui ci si trova. Le operazioni non lineari sono utili da applicare all'output di algoritmi
# come questo per generare una risposta di "attivazione".
deflection_angle = 0
# L'80 deriva dalla metà della risoluzione X, il 60 dalla metà della risoluzione Y. Il
# calcolo seguente non fa altro che determinare l'angolo di un triangolo in cui
# il lato opposto del triangolo è la deviazione della posizione centrale
# dal centro e il lato adiacente è metà della risoluzione Y. Questo limita
# l'angolo di uscita a circa -45/45. (Non è esattamente -45 e 45).
deflection_angle = -math.atan((center_pos - 80) / 60)
# Convertire l'angolo da radianti a gradi.
deflection_angle = math.degrees(deflection_angle)
# Ora si ha un angolo che indica di quanto girare il robot, che
# incorpora la parte della linea più vicina al robot e parti
# della linea più lontane dal robot, per una previsione migliore.
print("Turn Angle: %f" % deflection_angle)
print(clock.fps()) # Nota: la tua OpenMV Cam funziona a circa metà velocità quando
# è collegata al computer. Il framerate dovrebbe aumentare una volta scollegata.