實(shí)戰(zhàn):使用 OpenCV 的自動(dòng)駕駛汽車(chē)車(chē)道檢測(cè)(附代碼)
點(diǎn)擊上方“小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)

我們將使用 Canny 進(jìn)行邊緣檢測(cè)。如果你不確定這是什么,請(qǐng)查閱相關(guān)資料,對(duì)于后文的閱讀會(huì)有幫助。
def canyEdgeDetector(image):edged = cv2.Canny(image, 50, 150)return edged
駕駛時(shí),為了讓汽車(chē)保持在車(chē)道上,只關(guān)注當(dāng)前道路的下一個(gè)100米。此外,也不關(guān)心分隔線另一側(cè)的道路。這就是我們定義的區(qū)域。我們隱藏圖像中不必要的細(xì)節(jié),只顯示有助于我們找到車(chē)道的區(qū)域。

def getROI(image):height = image.shape[0]width = image.shape[1]# Defining Triangular ROI: The values will change as per your camera mountstriangle = np.array([[(100, height), (width, height), (width-500, int(height/1.9))]])# creating black image same as that of input imageblack_image = np.zeros_like(image)# Put the Triangular shape on top of our Black image to create a maskmask = cv2.fillPoly(black_image, triangle, 255)# applying mask on original imagemasked_image = cv2.bitwise_and(image, mask)return masked_image


4. 在我們的原始圖像上應(yīng)用蒙版以獲得只有我們的 ROI 的裁剪圖像。


下一步是通過(guò) ROI 以獲取圖像中的所有直線。cv2.HoughLinesP()可以實(shí)現(xiàn)這一目標(biāo),此函數(shù)返回它可以在輸入圖像中找到的所有直線的列表,每條線由 [x1, y1, x2, y2] 表示。
def getLines(image):lines = cv2.HoughLinesP(image, 0.3, np.pi/180, 100, np.array([]), minLineLength=70, maxLineGap=20)return lines

以下實(shí)用程序函數(shù)獲取圖像和線條列表,并在圖像上繪制線條。(此步驟不接受來(lái)自 Step3 的任何輸入。相反,這只是一個(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 arraycv2.line(image, (x1, y1), (x2, y2), (255, 0, 0), 10)return image
我們定義了另一個(gè)效用函數(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]y2 = int(y1 * (3.4 / 5))x1 = int((y1 - intercept) / slope)x2 = int((y2 - intercept) / slope)return np.array([x1, y1, x2, y2])

一旦我們從步驟 3 中獲得了線條,在這一步中,我們將這些線條分成 2 組(左和右)。如果你們注意到Step3的輸出圖像,則此步驟會(huì)將Line1和Line 2放入左側(cè)組,將Line3放入右側(cè)組。

分組后,我們找到該組的平均斜率(m)和截距(c),并嘗試通過(guò)調(diào)用 getLineCoordinatesFromParameters() 并傳遞平均值 m 和平均值 c 為每個(gè)組創(chuàng)建一條線。
以下是完成所有這些工作的函數(shù):
def getSmoothLines(image, lines):left_fit = [] # will hold m,c parameters for left side linesright_fit = [] # will hold m,c parameters for right side linesfor line in lines:y1, x2, y2 = line.reshape(4)parameters = np.polyfit((x1, x2), (y1, y2), 1)slope = parameters[0]intercept = parameters[1]if slope < 0:intercept))else:intercept))left_fit_average = np.average(left_fit, axis=0)right_fit_average = np.average(right_fit, axis=0)# now we have got m,c parameters for left and right line, we need to know x1,y1 x2,y2 parametersleft_line = getLineCoordinatesFromParameters(image, left_fit_average)right_line = getLineCoordinatesFromParameters(image, right_fit_average)return np.array([left_line, right_line])
這是線條分組后圖像的外觀:

image = cv2.imread("3.jpg") #Load Imageedged_image = canyEdgeDetector(image) # Step 1roi_image = getROI(edged_image) # Step 2lines = getLines(roi_image) # Step 3smooth_lines = getSmoothLines(image, lines) # Step 5image_with_smooth_lines = displayLines(image, smooth_lines) # Step 4cv2.imshow("Output", image_with_smooth_lines)cv2.waitKey(0)
輸出將如下所示:

Github代碼鏈接:
https://github.com/pdhruv93/computer-vision/tree/main/lane-detection-self-driving
交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~

