利用Python+OpenCV實(shí)現(xiàn)自動(dòng)駕駛汽車的車道線檢測(cè)
對(duì)于所有想知道如何在一篇文章中涵蓋這一概念的人,我想說,在你深入探索之前,事情聽起來很復(fù)雜。我不會(huì)說這篇文章非常簡(jiǎn)單,但是它的確是建立在非;A(chǔ)的計(jì)算機(jī)視覺概念之上的。
先決條件是什么?具備一些基本的OpenCV知識(shí)會(huì)很好。如果沒有,請(qǐng)不要擔(dān)心,我將嘗試解釋我將使用的OpenCV函數(shù),并為你提供參考,以更詳細(xì)地檢查它們。本文的每一節(jié)將介紹一個(gè)最終將在程序的主要部分中使用的函數(shù)。此外,在本文中,我將使用圖像演示所有內(nèi)容。你可以重用相同的代碼來使用視頻(因?yàn)橐曨l只是圖像的集合)。
步驟1:邊緣檢測(cè)我們將使用Canny邊緣檢測(cè)。如果你不確定這是什么,看看我之前的文章,它以實(shí)用的方式解釋了這一點(diǎn)。https://medium.com/analytics-vidhya/image-simplification-through-binarization-in-opencv-1292d91cae12def canyEdgeDetector(image):
edged = cv2.Canny(image, 50, 150)
return edged
這是我們應(yīng)用Canny邊緣檢測(cè)后的輸出結(jié)果
檢測(cè)Canny邊緣后輸出步驟2:定義ROI(感興趣區(qū)域)駕駛時(shí),為了讓汽車保持在車道上,你只關(guān)注當(dāng)前道路的下一個(gè)100米。而且,你也不關(guān)心護(hù)欄另一邊的路。這就是我們感興趣的區(qū)域。我們從圖像中隱藏不必要的細(xì)節(jié),只顯示能幫助我們找到車道的區(qū)域。
紅色的三角形表示我們感興趣的區(qū)域def getROI(image):
height = image.shape[0]
width = image.shape[1]
# Defining Triangular ROI: The values will change as per your camera mounts
triangle = np.a(chǎn)rray([[(100, height), (width, height), (width-500, int(height/1.9))]])
# creating black image same as that of input image
black_image = np.zeros_like(image)
# Put the Triangular shape on top of our Black image to create a mask
mask = cv2.fillPoly(black_image, triangle, 255)
# applying mask on original image
masked_image = cv2.bitwise_and(image, mask)
return masked_image
我們已經(jīng)定義了三角形ROI,它的坐標(biāo)將根據(jù)你安裝在你的汽車上的攝像頭的位置而變化(嘗試只擁有那部分圖像,這將實(shí)際有助于車道檢測(cè))。我們創(chuàng)建了一個(gè)與原始圖像相同形狀的黑色圖像:
創(chuàng)建一個(gè)與原始圖像相同形狀的黑色圖像創(chuàng)建蒙版:然后使用cv2.fillPoly()將我們的三角形(帶白色線條)放在我們的黑色圖像的頂部,創(chuàng)建一個(gè)蒙版。
創(chuàng)建一個(gè)面具在我們的原始圖像上應(yīng)用蒙版,得到只有我們的ROI的裁剪圖像。
原始圖像+蒙版=具有ROI的最終圖像這一步的輸出類似于:
getROI ()之后的輸出在得到感興趣區(qū)域之前進(jìn)行邊緣檢測(cè)是很重要的,否則邊緣檢測(cè)也會(huì)檢測(cè)出我們感興趣區(qū)域的邊界。步驟3:獲取圖像中的所有直線下一步是通過ROI得到圖像中的所有直線。houghlinesp()可以幫助你實(shí)現(xiàn)這一點(diǎn)。這個(gè)函數(shù)返回它能在輸入圖像中找到的所有直線的列表。每一行用[x1, y1, x2, y2]表示,F(xiàn)在,這看起來很簡(jiǎn)單,但是houghlinesp檢測(cè)的基本工作原理需要一點(diǎn)時(shí)間來解釋。所以我不會(huì)在本文中介紹它。相反,我建議你看一看此教程(#28,#29,#30應(yīng)該足以理解霍夫直線原則)。教程:https://www.youtube.com/watch?v=7m-RVJ6ABsYdef getLines(image):
lines = cv2.HoughLinesP(image, 0.3, np.pi/180, 100, np.a(chǎn)rray([]), minLineLength=70, maxLineGap=20)
return lines
必須根據(jù)你的需求調(diào)整cv2.HoughLinesP()的參數(shù)(嘗試更改和調(diào)試最適合你的)。但我認(rèn)為以上這些應(yīng)該在大多數(shù)情況下都適用。這一步的輸出是這樣的:
在圖像中檢測(cè)到3條線。圖像中可能檢測(cè)到數(shù)百條線。因此,調(diào)整參數(shù)以獲得盡可能少的線步驟4:一些實(shí)用函數(shù)下面的實(shí)用函數(shù)獲取圖像和線條列表,并在圖像上繪制線條。(這個(gè)步驟沒有從步驟3獲取任何輸入。相反,這只是一個(gè)將從Step5調(diào)用的實(shí)用程序步驟,因此你首先查看Step5并在需要時(shí)訪問該步驟)。def displayLines(image, lines):
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line.reshape(4) #converting to 1d array
cv2.line(image, (x1, y1), (x2, y2), (255, 0, 0), 10)
return image
我們定義了另一個(gè)實(shí)用函數(shù)來從它的參數(shù)(斜率和截距)得到線坐標(biāo)。記住,直線用y=mx+c表示,其中m是斜率,c是截距。def getLineCoordinatesFromParameters(image, line_parameters):
slope = line_parameters[0]
intercept = line_parameters[1]
y1 = image.shape[0] # since line will always start from bottom of image
y2 = int(y1 * (3.4 / 5)) # some random point at 3/5
x1 = int((y1 - intercept) / slope)
x2 = int((y2 - intercept) / slope)
return np.a(chǎn)rray([x1, y1, x2, y2])
注意我們是如何選擇y和y的值的步驟5:平滑線條一旦我們從步驟3中獲得了直線,在這一步中我們將這些直線分成兩組(左邊和右邊)。如果你注意到步驟3的輸出圖像,那么該步驟將把Line1和line2放到左邊的組中,而Line3放到右邊的組中。
如何在車道的左側(cè)和右側(cè)獲得一條公共線分組后,我們找到該組的平均斜率(m)和截距(c),并通過調(diào)用getLineCoordinatesFromParameters() 并傳遞平均值m和平均值c來為每個(gè)組創(chuàng)建一條線。下面是完成這一切的函數(shù):def getSmoothLines(image, lines):
left_fit = [] # will hold m,c parameters for left side lines
right_fit = [] # will hold m,c parameters for right side lines
for line in lines:
x1, y1, x2, y2 = line.reshape(4)
parameters = np.polyfit((x1, x2), (y1, y2), 1)
slope = parameters[0]
intercept = parameters[1]
if slope < 0:
left_fit.a(chǎn)ppend((slope, intercept))
else:
right_fit.a(chǎn)ppend((slope, intercept))
left_fit_average = np.a(chǎn)verage(left_fit, axis=0)
right_fit_average = np.a(chǎn)verage(right_fit, axis=0)
# now we have got m,c parameters for left and right line, we need to know x1,y1 x2,y2 parameters
left_line = getLineCoordinatesFromParameters(image, left_fit_average)
right_line = getLineCoordinatesFromParameters(image, right_fit_average)
return np.a(chǎn)rray([left_line, right_line])
這是線條分組后的圖像:
線分組后輸出主代碼(逐一調(diào)用上述步驟)一旦我們準(zhǔn)備好了各個(gè)函數(shù),我們只需要在我們的主代碼中調(diào)用它們,你就會(huì)在你的圖像中檢測(cè)到車道。image = cv2.imread("3.jpg") #Load Image
edged_image = canyEdgeDetector(image) # Step 1
roi_image = getROI(edged_image) # Step 2
lines = getLines(roi_image) # Step 3
smooth_lines = getSmoothLines(image, lines) # Step 5
image_with_smooth_lines = displayLines(image, smooth_lines) # Step 4
cv2.imshow("Output", image_with_smooth_lines)
cv2.waitKey(0)
輸出會(huì)像這樣:
具有確定車道的最最后的話終輸出你一直看到文章的結(jié)尾。對(duì)所有內(nèi)容進(jìn)行排序并使其適合圖像后,你便知道如何將其用于視頻。你可能已經(jīng)意識(shí)到你可以如何巧妙地使用非常基本的計(jì)算機(jī)視覺操作來實(shí)現(xiàn)如此有用的東西。我想說的是,不要把這項(xiàng)工作與特斯拉這樣的大公司做的比較(他們的基礎(chǔ)也是類似的)。把這作為動(dòng)力,也許在某個(gè)時(shí)候,你也能取得類似的成就。
END

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 5 國產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?