Deteksi Jalur Lengkung Canggih dengan OpenCV
Cerita
Pendahuluan
Markir jalur adalah tulang punggung setiap sistem pengemudi otonom, memandu kendaraan dengan aman melalui lalu lintas. Berdasarkan proyek deteksi jalur lurus saya sebelumnya, saya telah mengembangkan pipeline deteksi jalur lengkung yang andal yang bekerja dengan baik di lingkungan kompleks seperti bayangan, oklusi, dan permukaan jalan yang tidak rata.
Alur kerja pemrosesan citra lengkap diimplementasikan dalam Python menggunakan OpenCV:
- Koreksi distorsi
- Perspective warp
- Penyaringan Sobel
- Deteksi puncak histogram
- Pencarian jendela geser
- Penyusunan kurva polinomial
- Overlay jalur yang terdeteksi
- Pemrosesan video real-time
Keterbatasan Sistem Sebelumnya
Model sebelumnya terbatas pada jalur lurus dan kesulitan dengan lengkung, bayangan, dan oklusi parsial. Pipeline baru mengatasi keterbatasan ini dengan menggabungkan penyaringan berbasis tepi dan pendekatan jendela geser dinamis.
Koreksi Distorsi
Lensa kamera memperkenalkan distorsi radial yang dapat menyimpang pengukuran. Dengan mengkalibrasi kamera terhadap pola yang diketahui—biasanya papan catur asimetris—kita menghasilkan model distorsi yang memperbaiki seluruh dataset.
Prosedur kalibrasi melibatkan menangkap beberapa gambar papan catur, mendeteksi sudut dengan cv2.findChessboardCorners(), dan menghitung matriks kamera dan koefisien distorsi menggunakan cv2.calibrateCamera(). Gambar yang diperbaiki dihasilkan dengan cv2.undistort().
Di bawah ini adalah perbandingan sisi-by-sisi dari gambar papan catur yang tidak distort, menunjukkan perbaikan halus tetapi krusial.
Berikut adalah kode kalibrasi yang digunakan:
def undistort_img():
# Siapkan titik objek 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)
Fungsi-fungsi juga tersedia di buku catak Jupyter yang menyertakan di bagian Code.
Di bawah ini adalah contoh koreksi distorsi yang diterapkan pada scene mengemudi. Meski perbedaan visual halus, geometri yang akurat krusial untuk pemrosesan selanjutnya.
Perspective Warp
Mendeteksi jalur lengkung langsung di ruang kamera sulit. Dengan mentransformasi citra ke tampilan burung, kita dapat mengasumsikan jalur berada pada bidang datar dan menyusun polinomial dengan presisi tinggi.
Transformasi dilakukan dengan cv2.getPerspectiveTransform() dan cv2.warpPerspective(). Titik sumber dan tujuan dipilih untuk mempertahankan geometri jalur sambil memaksimalkan visibilitas.
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)
Penyaringan Sobel
Penyaringan warna saja dapat salah mengklasifikasi beton ringan sebagai markir jalur. Sebaliknya, kita menggunakan deteksi tepi berbasis gradien. Operator Sobel menghitung gradien horizontal di ruang warna HLS, menyoroti tepi jalur kontras tinggi sambil menekan permukaan jalan.
Mask biner yang dihasilkan tangguh terhadap variasi pencahayaan dan digunakan sebagai input untuk pencarian jendela geser.
Deteksi Puncak Histogram
Sebelum menerapkan jendela geser, kita mengidentifikasi posisi horizontal mendekati garis jalur dengan menghitung histogram citra biner sepanjang sumbu x. Puncak tertinggi di setiap sisi sesuai dengan titik dasar jalur kiri dan kanan.
Pencarian Jendela Geser
Menggunakan titik dasar, algoritma jendela geser secara iteratif mengumpulkan indeks piksel yang termasuk dalam setiap jalur. Kemudian itu menyusun polinomial derajat kedua untuk setiap jalur, memungkinkan estimasi lengkungan yang akurat dan posisi kendaraan relatif terhadap pusat jalur.
Overlay akhir menampilkan area jalur yang terdeteksi, lengkungan, dan offset kendaraan secara real-time.
Baca Lebih Detail: Deteksi Jalur Lengkung