Détection avancée de voies courbes avec OpenCV
Histoire
Introduction
Les marquages de voie sont la colonne vertébrale de tout système de conduite autonome, guidant les véhicules en toute sécurité dans le trafic. En m'appuyant sur mon précédent projet de détection de voies droites, j'ai développé un pipeline robuste de détection de voies courbes qui fonctionne de manière fiable dans des environnements complexes tels que les ombres, les occlusions et les surfaces routières inégales.
Le flux de travail complet de traitement d'image est implémenté en Python avec OpenCV :
- Correction de distorsion
- Transformation de perspective (warp)
- Filtrage Sobel
- Détection de pics d'histogramme
- Recherche par fenêtre glissante
- Ajustement de courbe polynomiale
- Superposition de la voie détectée
- Traitement vidéo en temps réel
Limitations du système précédent
Le modèle précédent était limité aux voies droites et peinait avec les courbes, les ombres et les occlusions partielles. Le nouveau pipeline résout ces lacunes en incorporant un filtrage basé sur les contours et une approche de fenêtre glissante dynamique.
Correction de distorsion
Les objectifs de caméra introduisent une distorsion radiale qui peut fausser les mesures. En calibrant la caméra contre un motif connu — généralement un damier asymétrique — nous générons un modèle de distorsion qui corrige l'ensemble du jeu de données.
La procédure de calibration implique la capture de multiples images du damier, la détection des coins avec cv2.findChessboardCorners(), et le calcul de la matrice de caméra et des coefficients de distorsion utilisant cv2.calibrateCamera(). Les images corrigées sont produites avec cv2.undistort().
Ci-dessous, une comparaison côte à côte d'une image de damier non déformée, démontrant l'amélioration subtile mais critique.
Code de calibration utilisé :
def undistort_img():
# Préparer points objet 0,0,0 … 8,5,0
obj_pts = np.zeros((6*9,3), np.float32)
obj_pts[:,:2] = np.mgrid[0:9, 0:6].T.reshape(-1,2)
objpoints = []
imgpoints = []
images = glob.glob('camera_cal/*.jpg')
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (9,6), None)
if ret:
objpoints.append(obj_pts)
imgpoints.append(corners)
img_size = (img.shape[1], img.shape[0])
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size, None, None)
dst = cv2.undistort(img, mtx, dist, None, mtx)
dist_pickle = {'mtx': mtx, 'dist': dist}
pickle.dump(dist_pickle, open('camera_cal/cal_pickle.p', 'wb'))
return dst
def undistort(img, cal_dir='camera_cal/cal_pickle.p'):
with open(cal_dir, 'rb') as f:
file = pickle.load(f)
mtx, dist = file['mtx'], file['dist']
return cv2.undistort(img, mtx, dist, None, mtx)
undistort_img()
img = cv2.imread('camera_cal/calibration1.jpg')
dst = undistort(img)
Les fonctions sont également disponibles dans le notebook Jupyter accompagnant sous la section Code.
Ci-dessous un exemple de correction de distorsion appliquée à une scène de conduite. Bien que la différence visuelle soit subtile, une géométrie précise est cruciale pour le traitement en aval.
Transformation de perspective (Perspective Warp)
Détecter des voies courbes directement dans l'espace caméra est difficile. En transformant l'image en vue aérienne (bird's-eye view), nous pouvons supposer que la voie se trouve sur un plan plat et ajuster un polynôme avec une haute précision.
La transformation est effectuée avec cv2.getPerspectiveTransform() et cv2.warpPerspective(). Les points source et destination sont choisis pour préserver la géométrie de la voie tout en maximisant la visibilité.
def perspective_warp(img, dst_size=(1280,720), src=np.float32([(0.43,0.65),(0.58,0.65),(0.1,1),(1,1)]), dst=np.float32([(0,0),(1,0),(0,1),(1,1)])):
img_size = np.float32([img.shape[1], img.shape[0]])
src = src * img_size
dst = dst * np.float32(dst_size)
M = cv2.getPerspectiveTransform(src, dst)
return cv2.warpPerspective(img, M, dst_size)
Filtrage Sobel
Le filtrage par couleur seul peut mal classer le béton clair comme marquage de voie. Au lieu de cela, nous utilisons la détection de contours basée sur le gradient. L'opérateur Sobel calcule les gradients horizontaux dans l'espace colorimétrique HLS, mettant en évidence les contours de voie à haut contraste tout en supprimant la surface de la route.
Le masque binaire résultant est robuste aux variations d'éclairage et sert d'entrée pour la recherche par fenêtre glissante.
Détection de pics d'histogramme
Avant d'appliquer la fenêtre glissante, nous identifions les positions horizontales approximatives des lignes de voie en calculant un histogramme de l'image binaire le long de l'axe x. Les pics les plus élevés de chaque côté correspondent aux points de base des voies gauche et droite.
Recherche par fenêtre glissante (Sliding Window Search)
En utilisant les points de base, l'algorithme de fenêtre glissante collecte itérativement les indices de pixels appartenant à chaque voie. Il ajuste ensuite un polynôme de second degré à chaque voie, permettant une estimation précise de la courbure et de la position du véhicule par rapport au centre de la voie.
La superposition finale affiche la zone de voie détectée, la courbure et le décalage du véhicule en temps réel.
En savoir plus : Détection de voies courbes
Processus de fabrication
- Capteur de distance ultrasonique basé 8051 – Conception, circuit et applications
- Systèmes de détection d'intrusion : protéger votre réseau avec alertes intelligentes
- Capteurs photoélectriques Omron E3AS-F : détection temps de vol 1,5 mètre
- Capteur ToF Hydra3D : détection 3D rapide et précise pour applications industrielles et extérieures
- Système d'alarme détection mouvement avec Java et Reactive Blocks – Déploiement sur Raspberry Pi et envoi SMS
- Farmaid : Robot autonome pour détection et marquage précis des maladies des plantes
- Intégration Microsoft Kinect avec Raspberry Pi pour détection humaine temps réel sur robot Sonbi
- Utilisation de la technologie des puces à ADN pour détecter l'expression génique en recherche clinique
- Fraisage CNC de précision pour surfaces courbes