周奇豐,凌莉萍
(蘇州建設(shè)交通高等職業(yè)技術(shù)學(xué)校,江蘇 蘇州 215000)
2020年11月11日,由北京市人民政府、工業(yè)和信息化部、公安部、交通運(yùn)輸部等共同主辦的“2020世界智能網(wǎng)聯(lián)汽車(chē)大會(huì)”召開(kāi),在會(huì)中發(fā)布了《智能網(wǎng)聯(lián)汽車(chē)技術(shù)路線圖2.0》。按照規(guī)劃,2025年,L2/L3級(jí)智能網(wǎng)聯(lián)汽車(chē)銷(xiāo)量占當(dāng)年汽車(chē)總銷(xiāo)量的比例超過(guò)50%。到2035年,中國(guó)方案智能網(wǎng)聯(lián)汽車(chē)技術(shù)和產(chǎn)業(yè)體系全面建成,產(chǎn)業(yè)生態(tài)健全完善,整車(chē)智能化水平顯著提升,網(wǎng)聯(lián)式高度自動(dòng)駕駛網(wǎng)聯(lián)汽車(chē)大規(guī)模應(yīng)用。而目前在L2/L3級(jí)的智能網(wǎng)聯(lián)汽車(chē)中攝像頭起到了至關(guān)重要的作用?;贠penCV視覺(jué)庫(kù)的車(chē)道線圖像處理技術(shù),能夠在視頻流中準(zhǔn)確實(shí)現(xiàn)車(chē)道線的實(shí)時(shí)檢測(cè)。
OpenCV(Open Source Computer Vision Library),是一個(gè)基于(開(kāi)源)發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)庫(kù),可以運(yùn)行在Linux、Windows和Mac OS操作系統(tǒng)上,能實(shí)現(xiàn)圖像處理和計(jì)算機(jī)視覺(jué)方面的很多通用算法。而NumPy可用來(lái)存儲(chǔ)和處理大型矩陣,比使用 Python本身處理要高效得多,支持高維度數(shù)組與矩陣的運(yùn)算,此外也針對(duì)數(shù)組提供了大量的數(shù)學(xué)函數(shù)庫(kù)。在車(chē)道線的圖像處理過(guò)程中,如圖1所示,重點(diǎn)在霍夫變換,難點(diǎn)在如何處理像素點(diǎn)。
圖1 車(chē)道線圖像識(shí)別主要步驟
圖像預(yù)處理之前,首先要了解什么是RGB圖像、灰度圖像和二值圖像[1]。在進(jìn)行圖像處理時(shí)需要將圖像中每一個(gè)像素點(diǎn)數(shù)值化后存放在圖像矩陣中。RGB圖像是指彩色圖像,分別用R(紅色)、G(綠色)和B(藍(lán)色)三個(gè)通道的顏色值來(lái)表示每個(gè)像素的顏色,每一個(gè)像素點(diǎn)有3個(gè)顏色分量?;叶葓D像是指黑白圖像,每一個(gè)像素點(diǎn)由0~255的取值構(gòu)成,其中0代表黑色,255代表白色。二值圖像僅由黑色和白色兩種顏色構(gòu)成,取值僅有0或1,0代表黑色,1代表白色。如圖2所示:
圖2 RGB圖像、灰度圖像和二值圖像
首先需要把圖像灰度化后導(dǎo)入程序中,如圖3所示:
圖3 導(dǎo)入灰度化的圖像
import cv2
import numpy as np
img=cv2.imread('C://Users//MIF//Desktop/chedaoxian2.jp g',cv2.IMREAD_GRAYSCALE)
高斯濾波是一種常用的濾波算法,可以有效地抑制噪聲,平滑圖像,減少圖像中噪點(diǎn)對(duì)與分析的影響[2]。高斯濾波的原理如圖4所示,對(duì)于某一個(gè)圖像,要對(duì)紅色的這個(gè)像素點(diǎn)高斯濾波,首先要選定一個(gè)核大小,圖示為3×3(任意奇數(shù)都可以)。對(duì)于紅色像素點(diǎn)核內(nèi)每一個(gè)像素點(diǎn)都有一個(gè)系數(shù),距離紅色像素點(diǎn)越近的像素點(diǎn)系數(shù)越大,距離紅色像素點(diǎn)越遠(yuǎn)的點(diǎn)系數(shù)越小。即讓臨近的像素點(diǎn)具有更高的重要度,對(duì)周?chē)袼赜?jì)算加權(quán)平均值,較近的像素具有較大的權(quán)重值,從而得到新的像素點(diǎn)的值。
圖4 高斯濾波原理
高斯濾波在OpenCV中使用cv2.GaussianBlur()這個(gè)函數(shù)來(lái)完成,如下所示:a=cv2.GaussianBlur(img,(5,5),0)。
在將圖像高斯濾波后,對(duì)圖像進(jìn)行邊緣檢測(cè),找出圖像的邊界點(diǎn)[3]。在OpenCV中可以選擇sobel算子、scharr算子或者laplacian算子來(lái)得出圖像梯度,經(jīng)過(guò)試驗(yàn)發(fā)現(xiàn)使用canny邊緣檢測(cè)來(lái)計(jì)算圖像的邊緣效果更好,如圖5所示:b=cv2. Canny(a,100,200,apertureSize =3)。
圖5 canny邊緣檢測(cè)后的圖像
圖像處理中的ROI,即感興趣區(qū)域。在圖像中可以選擇一個(gè)區(qū)域作為圖像處理關(guān)注的重點(diǎn),使用ROI可以減少圖像處理時(shí)間,減少資源占用。利用mask掩膜生成ROI時(shí),首先生成一個(gè)和原圖像大小一致的黑底圖像,然后利用坐標(biāo)畫(huà)出一個(gè)感興趣區(qū)域并且填充白色,利用函數(shù)cv2.bitwise_and()進(jìn)行與操作,保留白色區(qū)域的圖像,剔除黑色區(qū)域的圖像,如圖6所示:
圖6 mask掩膜
mask=np.zeros_like(img)
triangle=np.array([[0,753],[500,376],[640,376],[1073,753]])
cv2.fillPoly(mask,[triangle],(255,255,255))
mask_img=cv2.bitwise_and(mask,b)
經(jīng)過(guò)圖像的預(yù)處理,可以得到由多條線段構(gòu)成的圖像?;舴蜃儞Q的原理就是在笛卡爾坐標(biāo)系中,一條直線y=kx+b中由唯一的k、q相對(duì)應(yīng),我們把k、q分別作為x軸,y軸,可以得到霍夫空間。笛卡爾坐標(biāo)系中的一條線對(duì)應(yīng)霍夫空間中的一個(gè)點(diǎn)。反過(guò)來(lái)也同樣成立,霍夫空間中的一條線對(duì)應(yīng)笛卡爾坐標(biāo)系中的一個(gè)點(diǎn),如圖7所示:
圖7 霍夫變換原理1
如果在笛卡爾坐標(biāo)系中有幾個(gè)點(diǎn)共線,那么對(duì)應(yīng)到霍夫空間中就有幾條直線通過(guò)同一個(gè)點(diǎn),如圖8所示:
圖8 霍夫變換原理2
在笛卡爾坐標(biāo)系中,由多個(gè)點(diǎn)共不同直線的情況如圖9所示。在笛卡爾坐標(biāo)系中(1,1),(2,1),(4,1)這3個(gè)點(diǎn)共線,(3,2),(2,1),(1,0)這3個(gè)點(diǎn)共線。反映到霍夫空間中我們可以看出分別有A,B這兩個(gè)點(diǎn)由3條直線共點(diǎn)。而由于垂直于y軸的直線沒(méi)有k值,所以一般在處理的時(shí)候會(huì)采用極坐標(biāo)。因此,霍夫變換的目的就是在霍夫空間內(nèi)盡可能找到由更多條直線構(gòu)成的點(diǎn),可以設(shè)定閾值,篩選出不符合條件的點(diǎn)。
圖9 霍夫變換原理3
在OpenCV中,可以利用cv2.HoughLinesP()函數(shù)來(lái)完成霍夫變換,如下所示:
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(mask_img, 1, np.pi / 180,50, min LineLength, maxLineGap)
其中,mask_ing是我們預(yù)處理后的圖像;1是極坐標(biāo)的ρ;np.pi/180是極坐標(biāo)的θ;50是設(shè)定的閾值,超過(guò)50個(gè)像素點(diǎn)共線的直線才會(huì)被檢測(cè)出來(lái),值越大,被檢測(cè)出來(lái)的線段個(gè)數(shù)越少,值越小,被檢測(cè)出來(lái)的線段個(gè)數(shù)越多;minLine Length代表線段的最小長(zhǎng)度;maxLineGap代表同一方向上兩條線段判定為一條線段的最大允許間隔。經(jīng)過(guò)cv2.Hough LinesP()函數(shù)處理后的返回值是(x1,y1,x2,y2)四個(gè)元素的列表,其中(x1,y1)和(x2,y2)分別代表線段的兩個(gè)端點(diǎn)。
完成霍夫變換后,需要對(duì)cv2.HoughLinesP()的返回值進(jìn)行處理。處理的流程如圖10所示:
圖10 處理像素點(diǎn)集流程
(1)通過(guò)斜率正負(fù)判斷左右車(chē)道線,并分別添加入集合。
line_left=[]
line_right=[]
for line in lines:
for x1,y1,x2,y2 in line:
k=(y2-y1)/(x2-x1)
if k<0:
line_left.append(line)
else:
line_right.append(line)
(2)求出所有線段的斜率,并求平均值。分別計(jì)算出斜率列表中每一個(gè)元素與斜率平均值的差值,并且和平均值比較大小,超過(guò)設(shè)定閾值大小,刪除斜率不符合要求的點(diǎn)。
def clean_line(lines,threshould):
slope=[]
for line in lines:
for x1,y1,x2,y2 in line:
k=(y2-y1)/(x2-x1)
slope.append(k)
while len(lines)>0:
mean=np.mean(slope)
diff=[abs(s-mean) for s in slope]
idx=np.argmax(diff)
if diff[idx]>threshould:
slope.pop(idx)
lines.pop(idx)
else:
break
clean_line(line_left,0.5)
clean_line(line_right,0.5)
(3)分別提取左右兩側(cè)所有的點(diǎn),并放入列表中。
points_left=[]
for points in line_left:
for x1,y1,x2,y2 in points:
left=(x1,y1)
points_left.append(left)
left=(x2,y2)
points_left.append(left)
points_right=[(x1,y1) for line in line_right for x1,y1,x2,y2 in line]
points_right=points_right+[(x2,y2) for line in line_right for x1,y1,x2,y2 in line]
(4)分別在左右點(diǎn)的列表中找出y值的最大值和最小值。
point_left_y=[]
for i in points_left:
point_left_y.append(i[1])
print(point_left_y)
point_left_y_max=np.max(point_left_y)
point_left_y_min=np.min(point_left_y)
point_right_y=[]
for i in points_right:
point_right_y.append(i[1])
point_right_y_max=np.max(point_right_y)
point_right_y_min=np.min(point_right_y)
(5)用一次多項(xiàng)式擬合所有的點(diǎn),并且得到左右兩條線段的端點(diǎn)。
def fit_point_set(point_list,ymin,ymax):
x=[p[0] for p in point_list]
y=[p[1] for p in point_list]
fit=np.polyfit(y,x,1)
fit_set = np.poly1d(fit)
xmin=int(fit_set(ymin))
xmax=int(fit_set(ymax))
return [(xmin,ymin),(xmax,ymax)]
left_fps=fit_point_set(points_left,point_left_y_min,1073)
right_fps=fit_point_set(points_right,point_right_y_min,107 3)
以上程序就是對(duì)像素點(diǎn)集的處理,最終可以得到左右兩條擬合車(chē)道線的兩個(gè)端點(diǎn),通過(guò)左右分別4個(gè)點(diǎn),可以繪制出車(chē)道線。
繪制車(chē)道線時(shí)需要用OpenCV中的cv2.line()函數(shù),如下所示:
cv2.line(img,left_fps[0],left_fps[1],(0,0,0),5)
cv2.line(img,right_fps[0],right_fps[1],(0,0,0),5)
最終得到的繪制車(chē)道線的效果如圖11所示:
圖11 車(chē)道線繪制效果
本文不僅僅可以用于檢測(cè)車(chē)道線的圖片,也可以在視頻 流中檢測(cè)車(chē)道線,使用cv.VideoCapture()函數(shù)就可以實(shí)現(xiàn)車(chē)道的實(shí)時(shí)檢測(cè)。本文以對(duì)車(chē)道線進(jìn)行檢測(cè)這一簡(jiǎn)單任務(wù)為例,說(shuō)明openCV視覺(jué)庫(kù)的圖像處理技術(shù)優(yōu)勢(shì),例如檢測(cè)來(lái)自前方車(chē)輛的干擾,車(chē)道線不清晰,識(shí)別障礙物,根據(jù)車(chē)道線的位置判斷車(chē)輛的偏移情況等,都可以通過(guò)此項(xiàng)技術(shù)進(jìn)一步研究補(bǔ)充優(yōu)化。