使用OpenCV對車道進行實時檢測的實現示例程式碼
專案介紹
下圖中的兩條線即為車道:
我們的任務就是通過 OpenCV 在一段視訊(或攝像頭)中實時檢測出車道並將其標記出來。其效果如下圖所示:
這裡使用的程式碼來源於磐懟懟大神,此文章旨在對其程式碼進行解釋。
實現步驟
1、將視訊的所有幀讀取為圖片;
2、建立掩碼並應用到這些圖片上;
3、影象閾值化;
4、用霍夫線變換檢測車道;
5、將車道畫到每張圖片上;
6、將所有圖片合併為視訊。
程式碼實現
1、匯入需要的庫
import os import re import cv2 import numpy as np from tqdm import notebook import matplotlib.pyplot as plt
其中 tqdm.notebook 是用來顯示進度條的。
2、將圖片(視訊的每一幀)載入進來
這裡我們已經將視訊的每一幀讀取為圖片了,並將它們都放進 frames 資料夾。
# 獲取幀的檔名 col_frames = os.listdir('frames/') # 讀取 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) # 將所有圖片新增進 col_images 列表
3、選擇一張圖片進行處理
3.1 選定一張圖片
# 指定一個索引 idx = 457 # plot frame plt.figure(figsize=(10,10)) plt.imshow(col_images[idx][:,:,0],cmap= "gray") plt.show()
3.2 建立掩碼
# 建立0矩陣 stencil = np.zeros_like(col_images[idx][:,0]) # 指定多邊形的座標 polygon = np.array([[50,270],[220,160],[360,[480,270]]) # 用1填充多邊形 cv2.fillConvexPoly(stencil,polygon,1) # 畫出多邊形 plt.figure(figsize=(10,10)) plt.imshow(stencil,cmap= "gray") plt.show()
3.3 將掩碼應用到圖片上
# 應用該多邊形作為掩碼 img = cv2.bitwise_and(col_images[idx][:,col_images[idx][:,mask=stencil) # 畫出掩碼後的圖片 plt.figure(figsize=(10,10)) plt.imshow(img,cmap= "gray") plt.show()
這裡的按位與操作 cv2.bitwise_and() 可以參考OpenCV 之按位運算舉例解析一文。
3.4 影象閾值化
# 應用影象閾值化 ret,thresh = cv2.threshold(img,130,145,cv2.THRESH_BINARY) # 畫出影象 plt.figure(figsize=(10,10)) plt.imshow(thresh,cmap= "gray") plt.show()
其中 cv2.threshold 函式的用法可以參考Opencv之影象閾值一文。
3.5 霍夫線變換檢測車道
lines = cv2.HoughLinesP(thresh,1.0,np.pi/180,30,maxLineGap=200) # 建立原始幀的副本 dmy = col_images[idx][:,0].copy() # 霍夫線 for line in lines: x1,y1,x2,y2 = line[0] # 提取出霍夫線的座標 cv2.line(dmy,(x1,y1),(x2,y2),(255,0),3) # 將霍夫線畫在幀上 # 畫出幀 plt.figure(figsize=(10,10)) plt.imshow(dmy,cmap= "gray") plt.show()
cv2.HoughLinesP() 函式介紹:
lines = HoughLinesP(image,rho,theta,threshold,minLineLength=None,maxLineGap=None)
輸入:
- image: 必須是二值影象;
- rho: 線段以畫素為單位的距離精度,double型別的,推薦用1.0
- theta: 線段以弧度為單位的角度精度,推薦用numpy.pi/180
- threshod: 累加平面的閾值引數,int型別,超過設定閾值才被檢測出線段,值越大,基本上意味著檢出的線段越長,檢出的線段個數越少。
- minLineLength:線段以畫素為單位的最小長度。
- maxLineGap:同一方向上兩條線段判定為一條線段的最大允許間隔,超過了設定值,則把兩條線段當成一條線段。
輸出:
lines:一個三維矩陣,其形狀符合 (m,1,n),其中 m 表示直線個數,n 表示每條直線的兩端座標。
4、對每張圖片進行上一步驟的處理後寫入視訊
4.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)
4.2 處理所有圖片並寫入視訊檔案
for img in notebook.tqdm(col_images): # 應用幀掩碼 masked = cv2.bitwise_and(img[:,img[:,mask=stencil) # 應用影象閾值化 ret,thresh = cv2.threshold(masked,cv2.THRESH_BINARY) # 應用霍夫線變換 lines = cv2.HoughLinesP(thresh,maxLineGap=200) dmy = img.copy() #畫出檢測到的線 try: for line in lines: x1,y2 = line[0] cv2.line(dmy,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]]) cv2.fillConvexPoly(stencil,1) pathOut = 'roads_v2.mp4' fps = 30.0 height,height) out = cv2.VideoWriter(pathOut,size) for img in notebook.tqdm(col_images): masked = cv2.bitwise_and(img[:,mask=stencil) ret,cv2.THRESH_BINARY) lines = cv2.HoughLinesP(thresh,maxLineGap=200) dmy = img.copy() try: for line in lines: x1,3) out.write(dmy) except TypeError: out.write(img) out.release()
到此這篇關於使用OpenCV對車道進行實時檢測的實現示例程式碼的文章就介紹到這了,更多相關OpenCV 車道實時檢測內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!