使用OpenCV來實現自動駕駛中的車道線檢測

語言: CN / TW / HK

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第17天,點擊查看活動詳情

導讀

這是一個非常簡單通用的pipeline,很有參考價值。

圖片

在這個項目中,我使用Python和OpenCV構建了一個pipeline來檢測車道線。該pipeline包含以下步驟:

  • 相機校正
  • 視角轉換
  • 顏色閾值和區域掩碼
  • 尋找車道像素
  • 測量車道曲線和曲率
  • 在原圖像上顯示結果

1. 相機校正

當相機在現實世界中看到3D目標並將其轉換為2D圖像時,就會發生圖像失真,這種轉換並不完美。畸變實際上改變了這些3D物體的形狀和大小。所以,分析相機圖像的第一步,就是消除這種失真,這樣你就能從中得到有用的信息。

圖片

有兩種類型的畸變我們感興趣:徑向畸變切向畸變

為了校準相機,我們可以拍攝已知形狀的照片並校正失真誤差。這個任務最常見的拍攝對象是棋盤,因為它具有高對比度圖案。

首先,我們需要使用我們的相機來拍攝大量的棋盤圖像,並檢測這些圖像中的所有角點。這可以使用OpenCV的 cv2.findChessboardCorners()函數來完成。

圖片

cv2.findChessboardCorners()的結果

在這之後,我們使用cv2.calibrateCamera()來計算畸變係數。徑向畸變有3個係數:k1k2k3 ,切向畸變有2個係數:p1p2。畸變點座標計算公式如下,其中r為未畸變圖像中某一點到圖像畸變中心的已知距離,畸變中心通常是該圖像的中心(x_c, y_c)

圖片

徑向畸變公式

圖片

切向畸變公式

圖片

圖片

畸變校正之後的結果

2. 透視變換

在這一步,我們將圖像轉換為鳥瞰圖。它將使以後的步驟,如測量車道曲率更容易。要變換圖像,我們首先需要從源圖像上和目標圖像上分別得到4個點,並使用函數cv2.getPerspectiveTransform()。當我們想通過cv2.warpPerspective()函數變換圖像時,該函數計算一個出一個3x3的變換矩陣。

圖片

透視變換之前和之後的圖像

3. 顏色閾值和區域掩碼

圖片

HSV 和 HLS 顏色空間

HLS(色調,亮度,飽和度)是RGB模型的一種替代表示。HLS是圓柱形幾何圖形,具有色相,角度維度,是實際的顏色。亮度表示顏色中混合了多少白色(或黑色)的顏色,飽和度表示顏色中有多少灰色。飽和度值為0,表示大部分都是灰色。

車道線的顏色為白色和黃色,兩者都有一定範圍內的飽和度值。因此,我只選擇飽和度值在該範圍內的像素。此外,利用亮度通道過濾掉所有亮度值較小的像素,可以檢測出白色。

圖片

Hue, 亮度和飽和度值

區域掩碼是去除圖像中不太可能包含線的部分的過程。我們可以看到,車道線主要出現在圖片的下半部,因此,可以將圖像的上半部分像素屏蔽以增加我們的準確性,因為圖像現在只包含那些更加可能是車道線的部分。

4. 找車道線像素

下一步,我們需要分類哪些像素在左車道,右車道,或兩者都不在。在此之後,我們將找到可以最好擬合所有左車道像素的多項式方程,以及另一個最好擬合所有右車道像素的方程。

首先,我在圖像下半部分的所有列上對像素值做統計得到直方圖。在我們的閾值二值化圖像中,像素要麼為0,要麼為1,因此直方圖中最突出的兩個峯值可以很好地指示車道線基線的x位置。

圖片

我們可以用它作為搜索直線的起點。在這一點上,我們可以使用一個在圖像中向上移動的滑動窗口(沿着路進一步移動)來確定車道線的去向。

圖片

使用滑動窗口檢測車道線像素

5. 找到車道線曲線並度量彎曲度

我們已經估計了哪些像素屬於左車道線和右車道線(分別用藍色和紅色表示),並對這些像素位置擬合了一個多項式。我們可以用這個多項式來計算車道曲率的半徑以及車輛距離車道中心的距離。

回想一下,我們已經找到了車道線的方程:

圖片

這是關於y的函數,而不是x的原因是,變換後圖像中的車道線接近垂直,並且對於多個y值可能具有相同的x值。

這裏的單位xy是以像素為單位的,但是我們想將其轉換為米來計算車輛的車道曲率和位置。假設2條線之間的距離在像素座標中是700像素。在現實生活中,這個距離大約是3.7米。因此,水平方向上的每個像素相當於現實生活中的3.7/700米。我們設這個值為mx = 3.7/700。在垂直方向上做同樣的操作,我們得到my = 30/720,表示每720個像素對應垂直方向上的30米。轉可以這樣做:

圖片

從像素座標到真實世界座標的轉換

函數x=f(y)在任意點x處的曲率的半徑為:

圖片

這很容易計算因為我們只需要計算函數的一階和二階導數。

圖片

接下來,我們想要計算我們的汽車到車道中心的距離。這可以通過計算車道中心和圖像中心之間的水平距離(以像素為單位)來實現。在這之後,我們可以乘以常數mx 來轉換為真實的距離。

6. 把結果顯示回原圖像

最後一步是將前一步的結果與原始圖像結合起來。

為此,我們需要還原之前轉換的透視圖,並將輸出圖像放到原始圖像之上。

圖片

原圖 vs 輸出圖

總結

這種特殊的pipeline在正常和模糊的情況下工作得很好,在這些情況下車道線更難檢測。然而,由於這個pipeline 的參數數量有限,因此在雨雪等極端條件下,它的穩定性不夠好。

總而言之,只需將幾個算法放在一起,我們就可以創建一個檢測車道線的pipeline。首先,我們校正相機失真。然後,我們將其轉換為鳥瞰圖,過濾掉圖像中不相關的部分,並使用“滑動窗口”找到車道像素。“最後,我們計算了車道的方程,並測量了車道曲率。

代碼:https://github.com/Dt-Pham/Advanced-Lane-Lines

英文原文:https://medium.com/@dt99.pham/self-driving-car-finding-lane-lines-7f7312997a6f