使用OpenCV來實現自動駕駛中的車道線檢測
持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第17天,點選檢視活動詳情
導讀
這是一個非常簡單通用的pipeline,很有參考價值。
在這個專案中,我使用Python和OpenCV構建了一個pipeline來檢測車道線。該pipeline包含以下步驟:
- 相機校正
- 視角轉換
- 顏色閾值和區域掩碼
- 尋找車道畫素
- 測量車道曲線和曲率
- 在原影象上顯示結果
1. 相機校正
當相機在現實世界中看到3D目標並將其轉換為2D影象時,就會發生影象失真,這種轉換並不完美。畸變實際上改變了這些3D物體的形狀和大小。所以,分析相機影象的第一步,就是消除這種失真,這樣你就能從中得到有用的資訊。
有兩種型別的畸變我們感興趣:徑向畸變和切向畸變。
為了校準相機,我們可以拍攝已知形狀的照片並校正失真誤差。這個任務最常見的拍攝物件是棋盤,因為它具有高對比度圖案。
首先,我們需要使用我們的相機來拍攝大量的棋盤影象,並檢測這些影象中的所有角點。這可以使用OpenCV的 cv2.findChessboardCorners()
函式來完成。
cv2.findChessboardCorners()的結果
在這之後,我們使用cv2.calibrateCamera()
來計算畸變係數。徑向畸變有3個係數:k1
, k2
, k3
,切向畸變有2個係數:p1
, p2
。畸變點座標計算公式如下,其中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值。
這裡的單位x和y是以畫素為單位的,但是我們想將其轉換為米來計算車輛的車道曲率和位置。假設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。首先,我們校正相機失真。然後,我們將其轉換為鳥瞰圖,過濾掉影象中不相關的部分,並使用“滑動視窗”找到車道畫素。“最後,我們計算了車道的方程,並測量了車道曲率。
程式碼:http://github.com/Dt-Pham/Advanced-Lane-Lines
英文原文:http://medium.com/@dt99.pham/self-driving-car-finding-lane-lines-7f7312997a6f
- 知識蒸餾:如何用一個神經網路訓練另一個神經網路
- 自學成才的機器學習工程師十誡
- 使用OpenCV來實現自動駕駛中的車道線檢測
- 比監督學習做的更好:半監督學習
- Generalized Focal Loss論文解讀
- PyTorch中的In-place操作是什麼?為什麼要避免使用這種操作?
- 權值衰減和L2正則化傻傻分不清楚?
- 如何將PyTorch Lighting模型部署到生產服務中
- 【論文解讀】ACoL:對抗互補學習,弱監督物體定位方法
- 使用PyTorch來進展不平衡資料集的影象分類
- 在目標檢測中如何解決小目標的問題?
- 來自Google Research:寬模型和深模型學到的是相同的東西嗎?
- 使用SimCLR用對比預訓練模型實現半監督影象分類的程式碼實現
- RepPointv2:使用點集合表示來做目標檢測
- 用不需要手工標註分割的訓練資料來進行影象分割
- 使用合成數據集來做目標檢測:目標檢測的介紹
- 提升小目標檢測的一種新的包圍框相似度度量:Normalized Gaussian Wasserstein Distance
- CB Loss:基於有效樣本的類別不平衡損失
- EfficientNetV2:更小,更快,更好的EfficientNet
- 如何將“複製貼上”嵌入到影象修復中:Shift-Net使用深度特徵重排的影象修復方法