Epipolar Geometry
La geometria epipolare mette in relazione due viste di una scena e vincola la corrispondenza di ogni punto a una linea nell'altra immagine, costituendo la base della profondità stereo e della mappatura 3D.
Nella visione artificiale, la geometria epipolare descrive la relazione geometrica tra due viste della stessa scena riprese da due telecamere. Un pixel in un'immagine corrisponde a un raggio di possibili punti 3D, e quel raggio si proietta nella seconda immagine come una linea, detta linea epipolare, sulla quale deve trovarsi il pixel corrispondente. Il vincolo dipende solo dai parametri interni delle telecamere e dalla loro posa relativa, indipendentemente dalla struttura della scena, e trasforma la ricerca di una corrispondenza da una ricerca sull'intera immagine a una ricerca lungo una sola linea. Per questo la geometria epipolare è alla base della visione stereoscopica, della struttura dal movimento e dello SLAM visivo che guida robot e visori. Multiple View Geometry in Computer Vision di Richard Hartley e Andrew Zisserman è il testo di riferimento.
Epipoli, linee epipolari e piano epipolare#
I due centri delle telecamere e un punto qualsiasi della scena definiscono un piano, detto piano epipolare. La linea che congiunge i centri delle telecamere è la linea di base e interseca ciascun piano immagine nell'epipolo, cioè l'immagine del centro dell'altra telecamera, che può trovarsi fuori dall'inquadratura o all'infinito. Ogni piano epipolare interseca ciascuna immagine in una linea epipolare, detta anche epilinea, quindi tutte le linee epipolari di un'immagine passano per il suo epipolo. Quando il punto della scena scorre lungo il raggio visivo della prima telecamera, la sua proiezione nella seconda immagine scorre lungo la linea epipolare.
Matrici fondamentale ed essenziale#
La matrice fondamentale F, una matrice 3 × 3 di rango due, rappresenta l'intera relazione in coordinate pixel. Per i punti corrispondenti x e x′ scritti in forma omogenea (x, y, 1), il vincolo epipolare è x′ᵀ F x = 0 e il prodotto F x fornisce i coefficienti della linea epipolare di x nella seconda immagine. Quando le telecamere vengono calibrate tramite la calibrazione della telecamera, la matrice essenziale E = K′ᵀ F K esprime lo stesso vincolo in coordinate normalizzate e si scompone nella rotazione relativa R e nella traslazione t come E = [t]ₓ R. Christopher Longuet-Higgins introdusse la matrice essenziale e l'algoritmo degli otto punti nel 1981; nei primi anni Novanta, Olivier Faugeras, Quang-Tuan Luong e Richard Hartley svilupparono la matrice fondamentale non calibrata. Poiché E determina solo la direzione di t, con due sole viste la forma della scena è definita a meno di una scala sconosciuta, che può essere stabilita conoscendo la linea di base o le dimensioni di un oggetto.
Entrambe le matrici vengono stimate a partire da punti chiave abbinati, come le feature SIFT, usando uno stimatore robusto come RANSAC, che adatta ripetutamente la matrice a un campione minimo di corrispondenze e conserva il modello concordato dalla maggior parte delle corrispondenze. Questo esempio crea due viste di 100 punti, sostituisce 20 corrispondenze con corrispondenze casuali errate e stima F con la variante MAGSAC di RANSAC di OpenCV:
import cv2
import numpy as np
rng = np.random.default_rng(0)
K = np.array([[800.0, 0, 320], [0, 800.0, 240], [0, 0, 1]]) # intrinsics shared by both cameras
# 100 scene points seen by two cameras; the second sits 0.5 m to the right, turned 5 degrees
points = rng.uniform([-2, -1, 4], [2, 1, 8], (100, 3))
rvec = np.array([0.0, np.radians(5), 0.0])
tvec = -cv2.Rodrigues(rvec)[0] @ np.array([0.5, 0.0, 0.0])
x1 = cv2.projectPoints(points, np.zeros(3), np.zeros(3), K, None)[0].reshape(-1, 2) + rng.normal(0, 0.5, (100, 2))
x2 = cv2.projectPoints(points, rvec, tvec, K, None)[0].reshape(-1, 2) + rng.normal(0, 0.5, (100, 2))
x2[:20] = rng.uniform([0, 0], [640, 480], (20, 2)) # replace 20 matches with wrong ones
# Robust estimation keeps the matches that agree with a single fundamental matrix
F, inliers = cv2.findFundamentalMat(x1, x2, cv2.USAC_MAGSAC, 1.0)
kept = inliers.ravel() == 1
print(f"Kept {kept[20:].sum()} of 80 true matches and {kept[:20].sum()} of 20 wrong ones")
# Each point in image 1 defines a line a*x + b*y + c = 0 in image 2 that its match must lie on
lines = cv2.computeCorrespondEpilines(x1, 1, F).reshape(-1, 3)
dist = np.abs((lines[:, :2] * x2).sum(axis=1) + lines[:, 2])
print(f"Median distance to epipolar line: {np.median(dist[20:]):.2f} px (true), {np.median(dist[:20]):.0f} px (wrong)")
print(f"Wrong match that survived: {dist[:20][kept[:20]].round(2)} px from its line")L'algoritmo conserva 75 delle 80 corrispondenze vere e scarta 19 delle 20 errate. Le corrispondenze vere distano dalle rispettive linee epipolari una mediana di 0,43 pixel, determinata dal rumore di mezzo pixel, mentre quelle errate ne distano 144. L'unica corrispondenza errata che supera il controllo si trova casualmente a 0,61 pixel dalla propria linea, perché il vincolo confina una corrispondenza a una linea e solo l'aspetto può individuare il punto corretto lungo di essa.
Una rotazione pura non ha linea di base e un singolo piano è compatibile con molte matrici fondamentali altrettanto valide: in entrambi i casi si usa quindi un'omografia, la trasformazione 3 × 3 tra viste di un piano. ORB-SLAM inizializza la propria mappa adattando in parallelo un'omografia e una matrice fondamentale e conservando quella che spiega meglio le corrispondenze.
Rettificazione, disparità e profondità#
La rettificazione deforma una coppia stereo in modo che le linee epipolari diventino orizzontali e allineate, collocando ogni corrispondenza sulla stessa riga dell'immagine. Gli algoritmi di stereo matching eseguono quindi la ricerca su ogni riga; lo scarto tra le colonne delle corrispondenze, detto disparità d, fornisce la profondità Z = f × B / d, dove f è la lunghezza focale e B la linea di base: è così che i sistemi stereo producono mappe di stima della profondità. Il benchmark stereo KITTI valuta questi algoritmi su scene rettificate di guida autonoma.
Applicazioni oltre la visione stereoscopica#
Nella ricostruzione 3D, COLMAP verifica ogni coppia di immagini adattando matrici fondamentali, essenziali o omografie, ed elimina le coppie e le corrispondenze prive di sufficiente supporto geometrico. Le pipeline di image matching usano lo stesso controllo per scartare le corrispondenze false; la registrazione delle immagini sceglie invece il ramo dell'omografia descritto sopra quando la scena è piatta o la telecamera ruota soltanto, come nell'unione di panorami. Tra due fotogrammi ripresi da una telecamera in movimento, il vincolo epipolare vale solo per le superfici statiche, quindi i vettori di flusso ottico che lo violano rivelano oggetti in movimento indipendente. Nelle riprese multicamera della posa umana, la stessa persona viene associata tra le viste in base alla vicinanza delle sue articolazioni alle rispettive linee epipolari prima di triangolare uno scheletro 3D; un modello di stima della posa Ultralytics YOLO26 fornisce 17 punti chiave del corpo di COCO per ogni persona in ciascuna vista.










