導讀本文主要介紹如何使用 Python 和 OpenCV實現(xiàn)一個實時曲線道路檢測系統(tǒng)。(公眾號:OpenCV與AI深度學習)
背景介紹
在任何駕駛場景中,車道線都是指示交通流量和車輛應(yīng)行駛位置的重要組成部分。這也是開發(fā)自動駕駛汽車的一個很好的起點!在我之前的車道檢測項目的基礎(chǔ)上,我實現(xiàn)了一個曲線車道檢測系統(tǒng),該系統(tǒng)工作得更好,并且對具有挑戰(zhàn)性的環(huán)境更加穩(wěn)健。車道檢測系統(tǒng)是使用 OpenCV 庫用 Python 編寫的。下面是實現(xiàn)步驟:
- 畸變校正
- 透視變換
- Sobel濾波
- 直方圖峰值檢測
- 滑動窗口搜索
- 曲線擬合
- 覆蓋檢測車道
- 應(yīng)用于視頻
畸變矯正
相機鏡頭扭曲入射光以將其聚焦在相機傳感器上。盡管這對于我們捕捉環(huán)境圖像非常有用,但它們最終往往會稍微不準確地扭曲光線。這可能導致計算機視覺應(yīng)用中的測量不準確。然而,我們可以很容易地糾正這種失真。我們可以使用棋盤格來標定相機然后做畸變校正:
測試視頻中使用的相機用于拍攝棋盤格的 20 張照片,用于生成畸變模型。我們首先將圖像轉(zhuǎn)換為灰度,然后應(yīng)用cv2.findChessboardCorners()函數(shù)。我們已經(jīng)知道這個棋盤是一個只有直線的二維對象,所以我們可以對檢測到的角應(yīng)用一些變換來正確對齊它們。用cv2.CalibrateCamera()來獲取畸變系數(shù)和相機矩陣。相機已校準!
然后,您可以使用它cv2.undistort()來矯正其余的輸入數(shù)據(jù)。您可以在下面看到棋盤的原始圖像和校正后的圖像之間的差異:
實現(xiàn)代碼:
def undistort_img():
# Prepare object points 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)
# Stores all object points & img points from all images
objpoints = []
imgpoints = []
# Get directory for all calibration images
images = glob.glob('camera_cal/*.jpg')
for indx, fname in enumerate(images):
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (9,6), None)
if ret == True:
objpoints.append(obj_pts)
imgpoints.append(corners)
# Test undistortion on img
img_size = (img.shape[1], img.shape[0])
# Calibrate camera
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size, None,None)
dst = cv2.undistort(img, mtx, dist, None, mtx)
# Save camera calibration for later use
dist_pickle = {}
dist_pickle['mtx'] = mtx
dist_pickle['dist'] = dist
pickle.dump( dist_pickle, open('camera_cal/cal_pickle.p', 'wb') )
def undistort(img, cal_dir='camera_cal/cal_pickle.p'):
#cv2.imwrite('camera_cal/test_cal.jpg', dst)
with open(cal_dir, mode='rb') as f:
file = pickle.load(f) mtx = file['mtx']
dist = file['dist']
dst = cv2.undistort(img, mtx, dist, None, mtx)
return dst
undistort_img()
img = cv2.imread('camera_cal/calibration1.jpg')
dst = undistort(img) # Undistorted image
這是應(yīng)用于道路圖像的失真校正。您可能無法注意到細微的差異,但它會對圖像處理產(chǎn)生巨大影響。
透視變換
在相機空間中檢測彎曲車道并不是很容易。如果我們想鳥瞰車道怎么辦?這可以通過對圖像應(yīng)用透視變換來完成。這是它的樣子:
注意到什么了嗎?通過假設(shè)車道位于平坦的 2D 表面上,我們可以擬合一個多項式,該多項式可以準確地表示車道空間中的車道!這不是很酷嗎?
您可以使用cv2.getPerspectiveTransform()函數(shù)將這些變換應(yīng)用于任何圖像,以獲取變換矩陣,并將cv2.warpPerspective()其應(yīng)用于圖像。下面是代碼:
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
# For destination points, I'm arbitrarily choosing some points to be
# a nice fit for displaying our warped result
# again, not exact, but close enough for our purposes
dst = dst * np.float32(dst_size)
# Given src and dst points, calculate the perspective transform matrix
M = cv2.getPerspectiveTransform(src, dst)
# Warp the image using OpenCV warpPerspective()
warped = cv2.warpPerspective(img, M, dst_size)
return warped
Sobel濾波
在之前的版本中,我使用顏色過濾掉了車道線。然而,這并不總是最好的選擇。如果道路使用淺色混凝土代替瀝青,道路很容易通過彩色濾光片,管道會將其感知為白色車道線,此方法不夠穩(wěn)健。
相反,我們可以使用類似于邊緣檢測器的方法,這次過濾掉道路。車道線通常與道路具有高對比度,因此我們可以利用這一點。之前版本 1 中使用的Canny邊緣檢測器利用Sobel 算子來獲取圖像函數(shù)的梯度。OpenCV 文檔對它的工作原理有很好的解釋。我們將使用它來檢測高對比度區(qū)域以過濾車道標記并忽略道路。
我們?nèi)詫⒃俅问褂?HLS 色彩空間,這一次是為了檢測飽和度和亮度的變化。sobel 算子應(yīng)用于這兩個通道,我們提取相對于 x 軸的梯度,并將通過梯度閾值的像素添加到表示圖像中像素的二進制矩陣中。這是它在相機空間和車道空間中的樣子:
直方圖峰值檢測
我們將應(yīng)用一種稱為滑動窗口算法的特殊算法來檢測我們的車道線。但是,在我們應(yīng)用它之前,我們需要為算法確定一個好的起點。如果它從存在車道像素的位置開始,它會很好地工作,但是我們?nèi)绾问紫葯z測這些車道像素的位置呢?其實很簡單!
我們將獲得圖像相對于 X 軸的直方圖。下面直方圖的每個部分都顯示了圖像每列中有多少個白色像素。然后我們?nèi)D像每一側(cè)的最高峰,每條車道線一個。這是直方圖的樣子,在二值圖像旁邊:
滑動窗口搜索
滑動窗口算法將用于區(qū)分左右車道邊界,以便我們可以擬合代表車道邊界的兩條不同曲線。
算法本身非常簡單。從初始位置開始,第一個窗口測量有多少像素位于窗口內(nèi)。如果像素數(shù)量達到某個閾值,它將下一個窗口移動到檢測到的像素的平均橫向位置。如果沒有檢測到足夠的像素,則下一個窗口從相同的橫向位置開始。這一直持續(xù)到窗口到達圖像的另一邊緣。
落在窗口內(nèi)的像素被賦予一個標記。在下圖中,藍色標記的像素代表右側(cè)車道,紅色標記的像素代表左側(cè):
曲線擬合
項目的其余部分非常簡單。我們分別使用 對紅色和藍色像素應(yīng)用多項式回歸np.polyfit(),然后檢測器就完成了!
這是曲線的樣子:
繪制檢測車道
這是檢測系統(tǒng)的最后一部分,用戶界面!我們只需創(chuàng)建一個覆蓋層來填充檢測到的車道部分,然后我們最終可以將其應(yīng)用于視頻。一旦應(yīng)用于視頻檢測,您應(yīng)該會看到以下輸出:
結(jié)論
就是這樣,一個基本的彎曲車道檢測器!它比以前的版本好得多,它甚至可以處理彎曲的車道!但是,它仍然會在一定程度上受到陰影和道路紋理劇烈變化的影響。在我的下一個車道檢測項目中,我們將使用一些機器學習技術(shù)來開發(fā)一個非常強大的車道和車輛檢測系統(tǒng),謝謝!
完整代碼:
https://github.com/kemfic/Curved-Lane-Lines/blob/master/P4.ipynb
參考鏈接:
https://www.hackster.io/kemfic/curved-lane-detection-34f771
-
檢測器
+關(guān)注
關(guān)注
1文章
871瀏覽量
47799 -
機器學習
+關(guān)注
關(guān)注
66文章
8446瀏覽量
133129 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41596
原文標題:實戰(zhàn)|OpenCV實時彎道檢測(詳細步驟+源碼)
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論