Tutorial · Intermedio · 22 min di lettura
Calibrazione della camera e posa ArUco con OpenCV
Calibra una camera per robot con OpenCV, misura l'errore di riproiettione, rileva i marker ArUco e stima la posa del marker con unità e coordinate corrette.
Un’immagine della camera restituisce pixel, ma un robot ha bisogno di raggi e coordinate. La calibrazione della camera stima i parametri intrinseci che mappano i punti 3D nel sistema di riferimento della camera sui pixel e la distorsione introdotta dall’obiettivo. Una volta noti questi valori, un marker con geometria nota può fornire la propria posizione e orientamento rispetto alla camera.
I marker ArUco sono fiduciali binari quadrati con un ID. Rilevare i quattro angoli identifica il marker nell’immagine; la stima della posa combina quegli angoli in pixel, la dimensione reale del marker e i parametri calibrati della camera.
Comprendi gli risultati della calibrazione
La matrice della camera contiene le lunghezze focali e il centro ottico:
[ fx 0 cx ]
[ 0 fy cy ]
[ 0 0 1 ]
fx e fy sono espressi in pixel. cx e cy individuano il punto principale. I coefficienti di distorsione modellano effetti come la distorsione radiale a barile o a cuscinetto e lo decentramento tangenziale.
Questi valori appartengono a una camera, a un obiettivo, a un’impostazione di messa a fuoco e a una geometria dell’immagine. Cambiare la risoluzione ritagliando o ridimensionando può richiedere di regolare i parametri intrinseci; cambiare la messa a fuoco o sostituire l’obiettivo richiede una nuova calibrazione.
Stampa e misura un bersaglio di calibrazione
Una scacchiera è un bersaglio iniziale pratico perché i suoi angoli interni sono facili da definire. Misura con precisione il lato della casella. La scala della posa eredita questa unità: punti oggetto in metri producono traslazioni in metri; punti oggetto in millimetri producono millimetri.
Mantieni piatto il bersaglio. Un foglio arrotolato viola la geometria piana assunta dai punti oggetto. Montalo su materiale rigido se la precisione è importante.
Definisci il numero di angoli interni, non di caselle stampate. Una scacchiera con 10 per 7 caselle ha 9 per 6 angoli interni. Mescolare questi conteggi fa fallire il rilevamento anche quando l’immagine sembra nitida.
Raccogli un insieme di immagini utile
Raccogli almeno dieci viste riuscite come punto di partenza, poi aggiungi varietà invece di duplicati. Sposta la scacchiera in tutta l’immagine, inclinala su entrambi gli assi, varia la distanza e includi gli angoli vicino ai bordi dell’immagine, dove la distorsione è più forte. Mantieni lo schema nitido e completamente visibile.
Venti fotogrammi quasi identici e frontali forniscono meno informazioni di un numero inferiore di pose ben distribuite. Scarta la sfocatura da movimento e i fotogrammi in cui il rilevamento degli angoli è incerto. Usa la stessa risoluzione e le stesse impostazioni della camera previste per il funzionamento.
Per ogni immagine accettata, memorizza gli angoli rilevati nell’immagine e i corrispondenti punti oggetto piani (column × squareSize, row × squareSize, 0).
Calibra con OpenCV
Il flusso Python essenziale è:
import cv2
import numpy as np
pattern = (9, 6) # internal corners: columns, rows
square_size = 0.024 # metres
object_template = np.zeros((pattern[0] * pattern[1], 3), np.float32)
object_template[:, :2] = np.mgrid[0:pattern[0], 0:pattern[1]].T.reshape(-1, 2)
object_template *= square_size
object_points, image_points = [], []
for gray in calibration_images:
found, corners = cv2.findChessboardCorners(gray, pattern)
if not found:
continue
refined = cv2.cornerSubPix(
gray, corners, (11, 11), (-1, -1),
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001),
)
object_points.append(object_template.copy())
image_points.append(refined)
rms, camera_matrix, distortion, rvecs, tvecs = cv2.calibrateCamera(
object_points, image_points, gray.shape[::-1], None, None
)
Controlla che le immagini accettate non siano troppo poche prima di chiamare la calibrazione. Salva insieme la matrice, i coefficienti di distorsione, larghezza/altezza dell’immagine, definizione del bersaglio e data di calibrazione. Un file di sole matrici è facile da usare in modo errato in seguito.
Valida più del solo valore RMS restituito
L’errore di riproiettione radice media quadratica (RMS) riassume quanto i punti di calibrazione proiettati distino dai punti rilevati nell’immagine. Un valore più basso è in genere migliore, ma un solo numero può nascondere aree problematiche o un insieme di immagini debole.
Calcola l’errore di riproiettione per immagine ed esamina le viste peggiori. Sovrapponi i punti riproiettati alle immagini. Controlla i bordi architettonici retti dopo la raddrizzatura, soprattutto vicino agli angoli. Poi stima la posa di un bersaglio a una distanza nota e confronta la traslazione con una misura fisica.
Se una sola immagine domina l’errore, ispezionala ed eliminala solo per un motivo difendibile come la sfocatura o l’ordine errato degli angoli. Eliminare ripetutamente fotogrammi ad alto errore finché il numero non sembra buono può nascondere un modello o un bersaglio scarso.
Rileva un marker ArUco
Scegli un dizionario predefinito e genera i marker da quello stesso dizionario. Le griglie di bit più grandi offrono più ID, ma a dimensione fissa dell’immagine ogni bit riceve meno pixel. Stampa il marker con un bordo bianco di riserva e misura la lunghezza del lato del quadrato nero usata dal modello di posa.
dictionary = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_50)
parameters = cv2.aruco.DetectorParameters()
detector = cv2.aruco.ArucoDetector(dictionary, parameters)
corners, ids, rejected = detector.detectMarkers(frame)
La costruzione dell’API varia tra le versioni più vecchie di OpenCV, quindi adatta il codice alla documentazione ufficiale della versione installata. Le uscite dovrebbero comunque fornire quattro angoli ordinati dell’immagine per ogni marker rilevato.
Stima la posa con una dimensione nota del marker
Definisci gli angoli del marker nel proprio sistema di coordinate e risolvi il problema perspective-n-point. Per un lato s del marker, il risolutore specifico per quadrati di OpenCV si aspetta un ordine coerente degli angoli:
s = 0.080 # metres
object_corners = np.array([
[-s/2, s/2, 0],
[ s/2, s/2, 0],
[ s/2, -s/2, 0],
[-s/2, -s/2, 0],
], dtype=np.float32)
ok, rvec, tvec = cv2.solvePnP(
object_corners,
corners[0].reshape(4, 2),
camera_matrix,
distortion,
flags=cv2.SOLVEPNP_IPPE_SQUARE,
)
tvec è l’origine del marker espressa nel sistema di riferimento della camera e usa la stessa unità di lunghezza di s. rvec è un vettore di rotazione di Rodrigues, non angoli di Eulero. Usa cv2.Rodrigues() per ottenere una matrice di rotazione o trasformala attraverso il sistema di riferimento del robot.
Disegna gli assi proiettati e verificali fisicamente. Una traslazione positiva con un valore plausibile non basta se gli assi sono specchiati o se è stata inserita la dimensione sbagliata del marker.
Rendi la posa abbastanza stabile per un robot
La posa diventa rumorosa quando il marker occupa pochi pixel, è inclinato ripidamente, è sfocato o si avvicina al bordo dell’immagine. Migliora l’illuminazione e l’esposizione, usa un marker più grande, avvicinati oppure usa una scheda con più marker quando l’applicazione lo consente.
Filtra solo le pose valide e conserva le marche temporali. Un filtro passa-basso riduce il tremore ma aggiunge ritardo di controllo. Rifiuta risultati improvvisi usando l’errore di riproiettione, i limiti di distanza e i limiti di movimento invece di fare la media cieca di ogni rilevamento.
La posa del marker è relativa alla camera. Per comandare un braccio robotico o una base mobile, trasformala attraverso il supporto calibrato della camera in base_link o nella base del braccio. Un errore millimetro/metro qui crea un errore mille volte più grande.
Diagnosi i guasti comuni
- La raddrizzatura curva le linee rette: le viste di calibrazione non coprono abbastanza, il bersaglio non era piatto o la geometria dell’immagine è cambiata.
- La scala della distanza è sempre sbagliata: il lato del quadrato o del marker usa la misurazione o l’unità sbagliata.
- Gli assi della posa puntano nella direzione sbagliata: l’ordine degli angoli oggetto o la convenzione del sistema di riferimento è sbagliato.
- L’ID del marker sfarfalla: il marker è troppo piccolo, sfocato, stampato male o proviene da un dizionario diverso.
- La posa salta vicino a una vista frontale: l’ambiguità della posa planare e la debole geometria dei pixel richiedono viste migliori, inseguimento o vincoli di più marker.
- La calibrazione funziona solo a una risoluzione: i parametri intrinseci sono stati riutilizzati dopo un ritaglio o un ridimensionamento senza regolarli.
- Il movimento del robot è in ritardo rispetto al marker: uno smorzamento eccessivo o marche temporali obsolete nascondono la geometria attuale.
Usa il Simulatore di sensori per esplorare rumore, bias, filtraggio e latenza. Il Simulatore del braccio robotico mostra come una posa del bersaglio possa rimanere irraggiungibile anche quando la geometria della camera è corretta.
Esplora il grafo
Fa parte di queste costruzioni
Progetti e percorsi di apprendimento che includono questo tutorial.
Per approfondire