[機器視覺] 基於opencv-python的單張圖片中車道識別實現

項目背景

本項目是筆者希望基於駕駛模擬類遊戲 歐洲卡車模擬2(ETS2) 實現駕駛輔助系統的設想的一個基礎項目 車道識別

關於《歐洲卡車模擬2》

《歐洲卡車模擬2》是一款模擬經營類遊戲,在遊戲中玩家要駕駛卡車完成貨物運輸任務,並可以購買更多的車庫、卡車、掛車,從司機介紹所僱傭司機來爲你工作,組建自己的物流公司。遊戲中玩家可以改裝自己的卡車、掛車的幾乎每一個部件,從駕駛室到底盤到各種配件和內飾。穿越歐洲大陸,組建自己的運輸帝國。

項目基本思路

對於車道線檢測,首先需要使程序能夠檢測出單張圖片中的車道線,以此爲依據進一步拓展至視頻中的車道線檢測,並最終推至實時畫面中的車道線檢測。
對於單張圖片的車道線識別,我的思路如下:
我們默認攝像機在車內位置是不變的,因此路面在畫面中的位置大致是不變的,爲了降低噪聲影響,我們可以人爲選取路面位置作爲興趣區域,並對興趣區域進行邊緣檢測與直線識別操作,並最終輸出處理結果。

原圖
在這裏插入圖片描述

項目步驟

  • 圖像灰度處理
  • 高斯模糊降噪
  • ROI興趣區域掩膜
  • canny邊緣檢測
  • 霍夫直線檢測
  • 車道線擬合
  • 圖像結果輸出

圖像灰度處理

將原有的RGB三維色彩信息處理爲一維的灰度值

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

灰度處理結果
灰度處理結果

高斯濾波

降低圖片噪聲值,便於邊緣檢測

blur_ksize = 7 
blur_gray = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)

濾波後結果
高斯濾波結果

canny邊緣檢測

對圖片進行邊緣檢測,便於下一步的霍夫直線檢測

canny_lthreshold = 50          
canny_hthreshold = 80         
edges = cv2.Canny(blur_gray, canny_lthreshold, canny_hthreshold)

canny邊緣檢測結果
canny邊緣檢測結果

ROI興趣區域掩膜處理

通過人爲處理去除掉大部分的噪聲值,便於直線檢測


def roi_mask(img, np.array([[(0, 660), (0, img.shape[1]),(img.shape[1], img.shape[0]), (img.shape[1], 660) ,(1000, 560) ,(900, 560)]])):
    # 生成roi目標區域,排除大部分無關噪聲值
    mask = np.zeros_like(img)
    mask_color = 255
    cv2.fillPoly(mask, vertices, mask_color)
    masked_img = cv2.bitwise_and(img, mask)
    return masked_img

ROI處理結果
ROI處理結果

霍夫直線檢測、判斷車道位置

通過霍夫變換將邊緣圖中的直線進行匹配,並在記錄車道位置

rho = 1                         
theta = np.pi / 180             
threshold = 15                
min_line_length = 100         
max_line_gap = 40           
def draw_lines(img, lines, color=[255, 0, 0], thickness=16):
    # 畫線函數
    for line in lines:
        for x1, y1, x2, y2 in line:
            cv2.line(img, (x1, y1), (x2, y2), color, thickness)

def hough_lines(img, rho, theta, threshold,min_line_len, max_line_gap):
    # 生成線
    lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
                            minLineLength=min_line_len,
                            maxLineGap=max_line_gap)
    line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    draw_lines(line_img, lines)
    return line_img

車道標記結果
車道標記結果

圖像結果輸出

將車道位置與原圖拼合,輸出結果

img_res = cv2.add(img,line_img)

最終處理結果
在這裏插入圖片描述

全部代碼

import matplotlib.pyplot as plt
import matplotlib.image as mplimg
import numpy as np
from cv2 import cv2

blur_ksize = 5                  # Gaussian blur kernel size
canny_lthreshold = 50           # Canny edge detection low threshold
canny_hthreshold = 80          # Canny edge detection high threshold

                                # Hough transform parameters
rho = 1                         #rho的步長,即直線到圖像原點(0,0)點的距離
theta = np.pi / 180             #theta的範圍
threshold = 15                  #累加器中的值高於它時才認爲是一條直線
min_line_length = 150            #線的最短長度,比這個短的都被忽略
max_line_gap = 40              #兩條直線之間的最大間隔,小於此值,認爲是一條直線

def roi_mask(img, vertices):
    # 生成roi目標區域,排除大部分無關噪聲值
    mask = np.zeros_like(img)
    mask_color = 255
    cv2.fillPoly(mask, vertices, mask_color)
    masked_img = cv2.bitwise_and(img, mask)
    return masked_img


def draw_lines(img, lines, color=[255, 0, 0], thickness=16):
    # 畫線函數
    for line in lines:
        for x1, y1, x2, y2 in line:
            cv2.line(img, (x1, y1), (x2, y2), color, thickness)

def hough_lines(img, rho, theta, threshold,min_line_len, max_line_gap):
    # 生成線
    lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
                            minLineLength=min_line_len,
                            maxLineGap=max_line_gap)
    line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    draw_lines(line_img, lines)
    return line_img

def img_rogress(img):
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    blur_gray = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
    edges = cv2.Canny(blur_gray, canny_lthreshold, canny_hthreshold)
    return edges
    
if __name__ == "__main__":
    img = mplimg.imread("datapic/test (26).jpg")
    roi_vtx = np.array([[(0, 660), (0, img.shape[1]),(img.shape[1], img.shape[0]), (img.shape[1], 660) ,(1000, 560) ,(900, 560)]])

    pre_res = img_rogress(img)

    roi_edges = roi_mask(pre_res,roi_vtx)

    line_img = hough_lines(roi_edges, rho, theta, threshold,
                            min_line_length, max_line_gap)
    
    img_res = cv2.add(img,line_img)
    
    plt.imshow( img_res)
    plt.show()

後記

經過後面的一系列探索,本方法存在很大的侷限性,未來將會更新另一種新的車道檢測方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章