使用OpenCV對(duì)車道進(jìn)行實(shí)時(shí)檢測(cè)的實(shí)現(xiàn)示例代碼
項(xiàng)目介紹
下圖中的兩條線即為車道:
我們的任務(wù)就是通過(guò) OpenCV 在一段視頻(或攝像頭)中實(shí)時(shí)檢測(cè)出車道并將其標(biāo)記出來(lái)。其效果如下圖所示:
這里使用的代碼來(lái)源于磐懟懟大神,此文章旨在對(duì)其代碼進(jìn)行解釋。
實(shí)現(xiàn)步驟
1、將視頻的所有幀讀取為圖片;
2、創(chuàng)建掩碼并應(yīng)用到這些圖片上;
3、圖像閾值化;
4、用霍夫線變換檢測(cè)車道;
5、將車道畫到每張圖片上;
6、將所有圖片合并為視頻。
代碼實(shí)現(xiàn)
1、導(dǎo)入需要的庫(kù)
import os import re import cv2 import numpy as np from tqdm import notebook import matplotlib.pyplot as plt
其中 tqdm.notebook 是用來(lái)顯示進(jìn)度條的。
2、將圖片(視頻的每一幀)加載進(jìn)來(lái)
這里我們已經(jīng)將視頻的每一幀讀取為圖片了,并將它們都放進(jìn) frames 文件夾。
# 獲取幀的文件名 col_frames = os.listdir('frames/') # 讀取 frames 文件夾下的所有圖片 col_frames.sort(key=lambda f: int(re.sub('\D', '', f))) # 按名稱對(duì)圖片進(jìn)行排序 # 加載幀 col_images=[] for i in notebook.tqdm(col_frames): img = cv2.imread('frames/'+i) col_images.append(img) # 將所有圖片添加進(jìn) col_images 列表
3、選擇一張圖片進(jìn)行處理
3.1 選定一張圖片
# 指定一個(gè)索引 idx = 457 # plot frame plt.figure(figsize=(10,10)) plt.imshow(col_images[idx][:,:,0], cmap= "gray") plt.show()
3.2 創(chuàng)建掩碼
# 創(chuàng)建0矩陣 stencil = np.zeros_like(col_images[idx][:,:,0]) # 指定多邊形的坐標(biāo) polygon = np.array([[50,270], [220,160], [360,160], [480,270]]) # 用1填充多邊形 cv2.fillConvexPoly(stencil, polygon, 1) # 畫出多邊形 plt.figure(figsize=(10,10)) plt.imshow(stencil, cmap= "gray") plt.show()
3.3 將掩碼應(yīng)用到圖片上
# 應(yīng)用該多邊形作為掩碼 img = cv2.bitwise_and(col_images[idx][:,:,0], col_images[idx][:,:,0], mask=stencil) # 畫出掩碼后的圖片 plt.figure(figsize=(10,10)) plt.imshow(img, cmap= "gray") plt.show()
這里的按位與操作 cv2.bitwise_and() 可以參考OpenCV 之按位運(yùn)算舉例解析一文。
3.4 圖像閾值化
# 應(yīng)用圖像閾值化 ret, thresh = cv2.threshold(img, 130, 145, cv2.THRESH_BINARY) # 畫出圖像 plt.figure(figsize=(10,10)) plt.imshow(thresh, cmap= "gray") plt.show()
其中 cv2.threshold 函數(shù)的用法可以參考Opencv之圖像閾值一文。
3.5 霍夫線變換檢測(cè)車道
lines = cv2.HoughLinesP(thresh, 1.0, np.pi/180, 30, maxLineGap=200) # 創(chuàng)建原始幀的副本 dmy = col_images[idx][:,:,0].copy() # 霍夫線 for line in lines: x1, y1, x2, y2 = line[0] # 提取出霍夫線的坐標(biāo) cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3) # 將霍夫線畫在幀上 # 畫出幀 plt.figure(figsize=(10,10)) plt.imshow(dmy, cmap= "gray") plt.show()
cv2.HoughLinesP() 函數(shù)介紹:
lines = HoughLinesP(image, rho, theta, threshold, minLineLength=None, maxLineGap=None)
輸入:
- image: 必須是二值圖像;
- rho: 線段以像素為單位的距離精度,double類型的,推薦用1.0
- theta: 線段以弧度為單位的角度精度,推薦用numpy.pi/180
- threshod: 累加平面的閾值參數(shù),int類型,超過(guò)設(shè)定閾值才被檢測(cè)出線段,值越大,基本上意味著檢出的線段越長(zhǎng),檢出的線段個(gè)數(shù)越少。
- minLineLength:線段以像素為單位的最小長(zhǎng)度。
- maxLineGap:同一方向上兩條線段判定為一條線段的最大允許間隔,超過(guò)了設(shè)定值,則把兩條線段當(dāng)成一條線段。
輸出:
lines:一個(gè)三維矩陣,其形狀符合 (m, 1, n),其中 m 表示直線個(gè)數(shù),n 表示每條直線的兩端坐標(biāo)。
4、對(duì)每張圖片進(jìn)行上一步驟的處理后寫入視頻
4.1 定義視頻格式
# 輸出視頻路徑 pathOut = 'roads_v2.mp4' # 視頻每秒的幀數(shù) fps = 30.0 # 視頻中每一幀的尺寸 height, width = img.shape size = (width,height) # 寫入視頻 out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size)
4.2 處理所有圖片并寫入視頻文件
for img in notebook.tqdm(col_images): # 應(yīng)用幀掩碼 masked = cv2.bitwise_and(img[:,:,0], img[:,:,0], mask=stencil) # 應(yīng)用圖像閾值化 ret, thresh = cv2.threshold(masked, 130, 145, cv2.THRESH_BINARY) # 應(yīng)用霍夫線變換 lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200) dmy = img.copy() #畫出檢測(cè)到的線 try: for line in lines: x1, y1, x2, y2 = line[0] cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3) out.write(dmy) except TypeError: out.write(img) out.release()
完整代碼
import os import re import cv2 import numpy as np from tqdm import notebook import matplotlib.pyplot as plt col_frames = os.listdir('frames/') col_frames.sort(key=lambda f: int(re.sub('\D', '', f))) col_images=[] for i in notebook.tqdm(col_frames): img = cv2.imread('frames/'+i) col_images.append(img) stencil = np.zeros_like(col_images[0][:,:,0]) polygon = np.array([[50,270], [220,160], [360,160], [480,270]]) cv2.fillConvexPoly(stencil, polygon, 1) pathOut = 'roads_v2.mp4' fps = 30.0 height, width = img.shape size = (width,height) out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size) for img in notebook.tqdm(col_images): masked = cv2.bitwise_and(img[:,:,0], img[:,:,0], mask=stencil) ret, thresh = cv2.threshold(masked, 130, 145, cv2.THRESH_BINARY) lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200) dmy = img.copy() try: for line in lines: x1, y1, x2, y2 = line[0] cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3) out.write(dmy) except TypeError: out.write(img) out.release()
到此這篇關(guān)于使用OpenCV對(duì)車道進(jìn)行實(shí)時(shí)檢測(cè)的實(shí)現(xiàn)示例代碼的文章就介紹到這了,更多相關(guān)OpenCV 車道實(shí)時(shí)檢測(cè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python源碼學(xué)習(xí)之PyObject和PyTypeObject
今天給大家?guī)?lái)的是關(guān)于Python源碼的相關(guān)知識(shí)學(xué)習(xí),文章圍繞著PyObject和PyTypeObject展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06Python中exit、return、sys.exit()等使用實(shí)例和區(qū)別
這篇文章主要介紹了Python中exit、return、sys.exit()等使用實(shí)例和區(qū)別,本文是一個(gè)實(shí)際項(xiàng)目中的總結(jié),需要的朋友可以參考下2015-05-05Python實(shí)現(xiàn)執(zhí)行Shell命令并獲取輸出
這篇文章主要介紹了如何借助?os.system()?從?Python?腳本執(zhí)行?cmd?命令,以及如何借助?Python?中的?subprocess?模塊以更簡(jiǎn)單的方式從腳本執(zhí)行?cmd?命令,感興趣的小伙伴可以了解下2023-10-10Python編程快速上手——Excel到CSV的轉(zhuǎn)換程序案例分析
這篇文章主要介紹了Python Excel到CSV的轉(zhuǎn)換程序,結(jié)合具體案例形式分析了Python操作Excel到CSV轉(zhuǎn)換的操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2020-02-02python opencv鼠標(biāo)畫矩形框之cv2.rectangle()函數(shù)
鼠標(biāo)操作屬于用戶接口設(shè)計(jì),以前一直使用Qt來(lái)做,但是如果只需要簡(jiǎn)單的鼠標(biāo),鍵盤操作,直接調(diào)用opencv庫(kù)的函數(shù)也未嘗不可,下面這篇文章主要給大家介紹了關(guān)于python opencv鼠標(biāo)畫矩形框cv2.rectangle()函數(shù)的相關(guān)資料,需要的朋友可以參考下2021-10-10Python在Console下顯示文本進(jìn)度條的方法
Python是一門與php有點(diǎn)像的編輯語(yǔ)言了,下文來(lái)給各位在利用Python實(shí)現(xiàn)進(jìn)度條了,對(duì)Python在Console下顯示文本進(jìn)度條的方法相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-02-02PYTHON如何讀取和寫入EXCEL里面的數(shù)據(jù)
這篇文章主要介紹了PYTHON如何讀取和寫入EXCEL里面的數(shù)據(jù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10