利用Python+OpenCV實(shí)現(xiàn)自動(dòng)駕駛汽車的車道線檢測(cè)
對(duì)于所有想知道如何在一篇文章中涵蓋這一概念的人,我想說(shuō),在你深入探索之前,事情聽(tīng)起來(lái)很復(fù)雜。我不會(huì)說(shuō)這篇文章非常簡(jiǎn)單,但是它的確是建立在非;A(chǔ)的計(jì)算機(jī)視覺(jué)概念之上的。
先決條件是什么?具備一些基本的OpenCV知識(shí)會(huì)很好。如果沒(méi)有,請(qǐng)不要擔(dān)心,我將嘗試解釋我將使用的OpenCV函數(shù),并為你提供參考,以更詳細(xì)地檢查它們。本文的每一節(jié)將介紹一個(gè)最終將在程序的主要部分中使用的函數(shù)。此外,在本文中,我將使用圖像演示所有內(nèi)容。你可以重用相同的代碼來(lá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:獲取圖像中的所有直線下一步是通過(guò)ROI得到圖像中的所有直線。houghlinesp()可以幫助你實(shí)現(xiàn)這一點(diǎn)。這個(gè)函數(shù)返回它能在輸入圖像中找到的所有直線的列表。每一行用[x1, y1, x2, y2]表示,F(xiàn)在,這看起來(lái)很簡(jiǎn)單,但是houghlinesp檢測(cè)的基本工作原理需要一點(diǎn)時(shí)間來(lái)解釋。所以我不會(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è)步驟沒(méi)有從步驟3獲取任何輸入。相反,這只是一個(gè)將從Step5調(diào)用的實(shí)用程序步驟,因此你首先查看Step5并在需要時(shí)訪問(wèn)該步驟)。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ù)來(lái)從它的參數(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),并通過(guò)調(diào)用getLineCoordinatesFromParameters() 并傳遞平均值m和平均值c來(lái)為每個(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ī)視覺(jué)操作來(lái)實(shí)現(xiàn)如此有用的東西。我想說(shuō)的是,不要把這項(xiàng)工作與特斯拉這樣的大公司做的比較(他們的基礎(chǔ)也是類似的)。把這作為動(dòng)力,也許在某個(gè)時(shí)候,你也能取得類似的成就。
END

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
7月22-29日立即報(bào)名>> 【線下論壇】第三屆安富利汽車生態(tài)圈峰會(huì)
-
7.30-8.1火熱報(bào)名中>> 全數(shù)會(huì)2025(第六屆)機(jī)器人及智能工廠展
-
7月31日免費(fèi)預(yù)約>> OFweek 2025具身智能機(jī)器人產(chǎn)業(yè)技術(shù)創(chuàng)新應(yīng)用論壇
-
免費(fèi)參會(huì)立即報(bào)名>> 7月30日- 8月1日 2025全數(shù)會(huì)工業(yè)芯片與傳感儀表展
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍(lán)皮書(shū)》
-
8月5日立即報(bào)名>> 【在線會(huì)議】CAE優(yōu)化設(shè)計(jì):醫(yī)療器械設(shè)計(jì)的應(yīng)用案例與方案解析
推薦專題
- 1 AI 眼鏡讓百萬(wàn) APP「集體失業(yè)」?
- 2 豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
- 3 一文看懂視覺(jué)語(yǔ)言動(dòng)作模型(VLA)及其應(yīng)用
- 4 “支付+”時(shí)代,支付即生態(tài) | 2025中國(guó)跨境支付十大趨勢(shì)
- 5 中國(guó)最具實(shí)力AI公司TOP10
- 6 深圳跑出40億超級(jí)隱形冠軍:賣機(jī)器人年入6.1億,港股上市
- 7 特斯拉Robotaxi上路,馬斯克端上畫(huà)了十年的餅
- 8 “AI六小虎”到了下一個(gè)賽點(diǎn)
- 9 AI視頻,攪動(dòng)1.5萬(wàn)億市場(chǎng)
- 10 張勇等人退出阿里合伙人