作者:Dt Pham
編譯:McGL

在這個項目中,我使用 Python 和 OpenCV 構建了一個 pipeline 來檢測車道線。這個 pipeline 包含以下步驟:
-
攝像頭校准(Camera calibration) -
透視變換(Perspective transformation) -
顏色閾值和區域掩碼(Color thresholding and Region masking) -
尋找車道像素(Finding lane pixels) -
測量車道曲線和曲率(Measuring lane curves and curvatures) -
將結果顯示回原始圖像(Display the result back to original image)
1. 攝像頭校准
當攝像頭觀察現實世界中的 3D 物體並將其轉換成 2D 圖像時,就會發生畸變; 這種轉換並不完美。畸變實際上改變了這些 3D 物體的形狀和大小。所以,分析攝像頭圖像的第一步,就是消除這種失真,這樣你就可以從中得到有用的信息。
我們感興趣的畸變有兩種類型: 徑向畸變(radial distortion)和切向畸變(tangential distortion)。
為了校准攝像頭,我們可以拍攝已知形狀的照片,並糾正任何畸變的錯誤。這項任務最常見的目標是棋盤,因為它的高對比度模式。
首先,我們需要用我們的攝像頭拍攝大量的棋盤圖像,並檢測這些圖像所有的角。這可以通過 OpenCV 中的函數 cv2.findchesspardcorners() 來實現。

之后,我們將使用 cv2.calibrateCamera()來求解畸變系數。修正徑向畸變需要三個系數: k1,k2,k3;而修正切向畸變需要兩個系數: p1,p2。計算畸變點坐標的公式如下所示,其中 r 是未畸變圖像中某點與圖像畸變中心之間的已知距離,而該中心通常就是圖像的中心 (x_c,y_c)




2. 透視變換
在這一步中,我們將把圖像轉換為鳥瞰圖。這將使以后的步驟,如測量車道曲率更容易。要對圖像進行變換,首先需要從源圖像取4個點,並從目標圖像取4個點,然后使用函數 cv2.getPerspectiveTransform() 進行變換。這個函數計算一個 3x3 變換矩陣,當我們想要通過 cv2.warpPerspective() 函數對圖像進行變換時,這個函數是必需的。

3. 色彩閾值和區域掩碼

HLS (色相,明度,飽和度)是 RGB 模型的一種替代表示。HLS 是圓柱形幾何體,色相(維的角度)是實際的色彩。明度是指顏色中混合了多少白色(或黑色) ,而飽和度值是指顏色中有多少灰色。飽和度值為0表示大部分為灰色,100%亮 (L=255)為白色。
車道線的顏色是白色和黃色,並且兩者都有特定范圍內的飽和度值。因此,我只選擇飽和度值在這個范圍之間的像素。通過過濾掉明度值較小的像素點,可以在明度信道中檢測出白色。

區域掩碼是消除圖像中不太可能包含車道線的部分的過程。我們可以看到,車道線大多出現在圖像的下半部分,因此在圖像的上半部分屏蔽像素將提高我們檢測車道線的准確率,因為圖像現在只包含更有可能是車道線的一部分的像素。
4. 尋找車道像素
下一步,我們需要分類哪些像素位於左車道、右車道或兩者都不是。之后,我們將找到最適合所有左車道像素的多項式方程和最適合所有右車道像素的另一個方程。
首先,我對圖像下半部分的所有列都做了一個直方圖。在我們的閾值化二值圖像中,像素要么是0,要么是1,所以這個直方圖中最突出的兩個峰值將很好地指示車道線基線的 x 位置。
我們可以用它作為搜索線條的起點。然后,在圖像上我們可以使用一個滑動窗口向上移動(進一步沿着道路) ,以確定在車道線走向。

5. 尋找車道曲線並測量曲率
我們已經估計了哪些像素屬於左線和右線(分別以藍色和紅色顯示) ,並且我們已經擬合了這些像素位置的多項式。我們可以用這個多項式來計算車道曲率的半徑以及車輛離車道中心的距離。
回憶一下,我們找車道線的方程式:
這是 y 而不是 x 的函數的原因是,因為在轉換后的圖像中,車道線是近乎垂直的,可能多個 y 值具有相同的 x 值。
這里 x 和 y 的單位是像素,但是我們想把它轉換成米來計算車道曲率和車輛的位置。假設兩條車道線之間的距離(像素坐標)為700像素。在現實生活中,這個距離大約是12英尺或3.7米。因此,水平方向上的每個像素相當於現實生活中的3.7/700米。我們把這個值稱為 mx = 3.7/700。在垂直方向上做同樣的操作,我們得到 my = 30/720,每720個垂直像素表示30米。轉換過程是這樣的:

函數 x=f(y) 任意點的曲率半徑如下得出:
這很容易計算,因為我們只需要計算我們的函數的一階和二階導數。
接下來,我們要計算我們的車離車道中心有多遠。這可以通過計算車道中心和圖像中心之間的水平距離(以像素為單位)來實現。之后,我們可以乘以常量 mx 來轉換為現實中的距離。
6. 將結果顯示回原始圖像
最后一步是將前一步的結果與原始圖像結合起來。
要做到這一點,我們需要恢復前面所做的透視變換,並將輸出圖像置於原始圖像之上。

總結
這個特殊的 pipeline 在正常和陰暗(這時車道線很難看見)的條件下工作良好。然而,由於這個 pipeline 的參數數量有限,它不夠魯邦,無法在雨雪等極端條件下表現良好。
總而言之,只要把幾個算法放在一起,我們就可以創建一個能夠檢測車道線的 pipeline。首先,我們對攝像頭失真進行了校正。然后,我們將其轉換為鳥瞰圖,過濾掉圖像中不相關的部分,並使用“滑動窗口”找到車道像素。最后,計算車道線方程並測量車道曲率。詳細的實現,請查看我 Github 上的項目:https://github.com/Dt-Pham/Advanced-Lane-Lines
來源:https://medium.com/@dt99.pham/self-driving-car-finding-lane-lines-7f7312997a6f