基于OpenCV的車輛變道檢測(cè)
點(diǎn)擊上方“小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)

本期教程我們將和小伙伴們一起研究如何使用計(jì)算機(jī)視覺(jué)和圖像處理技術(shù)來(lái)檢測(cè)汽車在行駛中時(shí)汽車是否在改變車道!大家一定聽(tīng)說(shuō)過(guò)使用OpenCV 的haar級(jí)聯(lián)文件可以檢測(cè)到面部、眼睛等,但是如果目標(biāo)是汽車,公共汽車呢?
我們將道路上汽車的視頻文件用作數(shù)據(jù)集。當(dāng)然可以使用圖像數(shù)據(jù)集檢測(cè)來(lái)汽車,但是由于汽車在變道時(shí)我們需要通過(guò)彈出窗口提供警報(bào),因此對(duì)于這些動(dòng)態(tài)情況,視頻輸入更為可行。
第一步是提供要在本教程中使用的輸入-OpenCV的haar級(jí)聯(lián)文件,用于檢測(cè)汽車的坐標(biāo),道路上的汽車的視頻文件-
cascade_src = 'cascade/cars.xml'video_src = 'dataset/cars.mp4'cap = cv2.VideoCapture(video_src)car_cascade = cv2.CascadeClassifier(cascade_src)
cv2.VideoCapture()方法用于捕獲輸入視頻,視頻通常為每秒25個(gè)圖像/幀(fps)。捕獲輸入后,使用循環(huán)提取幀,并使用汽車的haar級(jí)聯(lián)文件檢測(cè)到的坐標(biāo),我們?cè)谘h(huán)中在汽車周圍繪制一個(gè)矩形,以在對(duì)捕獲的幀執(zhí)行其他操作時(shí)獲得一致性。
while(1):# Take each frame_, frame = cap.read()cars = car_cascade.detectMultiScale(frame, 1.1, 1)for (x,y,w,h) in cars:roi = cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2) #ROI is region of interest
在OpenCV中,使用BGR而不是RGB,因此(0,0,255)將在汽車上繪制一個(gè)紅色矩形,而不是藍(lán)色。

如果幀的分辨率很高,則會(huì)減慢執(zhí)行的操作,此外,該幀還包含噪聲,可以使用模糊降低噪聲,這里使用高斯模糊。
3.1 HSV框架
在此,我們使用從cv2.VideoCapture()捕獲的幀中獲得的HSV幀僅突出顯示汽車轉(zhuǎn)彎的點(diǎn),并遮擋其余道路和在道路上直行的汽車。設(shè)置上限和下限閾值是為了定義HSV中的顏色范圍,以查看汽車改變車道的點(diǎn),并用作框架的遮罩。以下是用于獲取此代碼的代碼段-
#canceling noise in the video frames using blurframe = cv2.GaussianBlur(frame,(21,21),0)# Convert BGR to HSVhsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)# define range of color in HSV to see the points at which the car is changing angleslower_limit = np.array([0,150,150])upper_limit = np.array([10,255,255])# Threshold the HSV image to get only the thresholded colorsmask = cv2.inRange(hsv, lower_limit, upper_limit)
3.2腐蝕與膨脹
腐蝕和膨脹是圖像處理中常使用的兩個(gè)基本形態(tài)學(xué)操作。腐蝕算子在內(nèi)核區(qū)域上具有局部最小值的作用。腐蝕用于減少圖像中的斑點(diǎn)噪聲,斑點(diǎn)會(huì)從圖像中的對(duì)象邊界腐蝕掉。膨脹具有局部最大值運(yùn)算符的作用。當(dāng)添加像素以平滑圖像中對(duì)象的邊界時(shí),將使用膨脹來(lái)重新獲得一些丟失的區(qū)域。現(xiàn)在,通過(guò)基本形態(tài)學(xué)操作(腐蝕和膨脹)處理從HSV幀的第一步生成的蒙版。通過(guò)將幀和掩碼之間的按位與運(yùn)算應(yīng)用于獲取 ROI(感興趣區(qū)域),可以生成結(jié)果幀。
kernel = np.ones((3,3),np.uint8)kernel_lg = np.ones((15,15),np.uint8)# image processing technique called the erosion is used for noise reductionmask = cv2.erode(mask,kernel,iterations = 1)# image processing technique called the dilation is used to regain some lost areamask = cv2.dilate(mask,kernel_lg,iterations = 1)# Bitwise-AND to get black everywhere else except the region of interestresult = cv2.bitwise_and(frame,frame, mask= mask)
3.3車道檢測(cè)
canny邊緣檢測(cè)器與霍夫線變換一起用于檢測(cè)車道。

canny邊緣檢測(cè)(作者提供的圖像)
諸如canny邊緣檢測(cè)器之類的算法用于查找將圖像中的邊緣像素,但是由于我們無(wú)法融合某些點(diǎn)和邊緣,因此它無(wú)法找到實(shí)際對(duì)象,在這里我們可以使用OpenCV中的cv2.findContours()實(shí)現(xiàn)輪廓的查找。
定義-“輪廓是代表圖像中曲線的點(diǎn)的列表。”?等高線由序列表示(序列是結(jié)構(gòu)的鏈表),每個(gè)序列都編碼有關(guān)下一點(diǎn)位置的信息。我們?cè)赗OI中多次運(yùn)行cv2.findContours()以獲得實(shí)體,然后使用cv2.drawContours()繪制輪廓區(qū)域。等高線可以是點(diǎn),邊,多邊形等,因此在繪制等高線時(shí),我們進(jìn)行多邊形近似,以找到邊的長(zhǎng)度和區(qū)域的面積。函數(shù)cv2.drawContours()的工作方式是從根節(jié)點(diǎn)開(kāi)始繪制一棵樹(shù)(數(shù)據(jù)結(jié)構(gòu)),然后將后續(xù)點(diǎn),邊界框和freeman鏈代碼連接在一起。
找到輪廓后的另一個(gè)重要任務(wù)是匹配它們。輪廓匹配意味著我們有兩個(gè)單獨(dú)的計(jì)算輪廓相互比較,或者輪廓與抽象模板相比較。
thresh = maskcontours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)# define a minimum area for a contour (ignoring all values below min)min_area = 1000cont_filtered = []# filter out all contours below a min_areafor cont in contours:if cv2.contourArea(cont) > min_area:cont_filtered.append(cont)cnt = cont_filtered[0]# draw the rectangles around contoursrect = cv2.minAreaRect(cnt)box = cv2.boxPoints(rect)box = np.int0(box)cv2.drawContours(frame,[box],0,(0,0,255),2)rows,cols = thresh.shape[:2][vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)lefty = int((-x*vy/vx) + y)righty = int(((cols-x)*vy/vx)+y)cv2.line(frame,(cols-1,righty),(0,lefty),(0,255,0),2)
我們可以通過(guò)計(jì)算輪廓矩來(lái)比較兩個(gè)輪廓。“中心矩是通過(guò)將輪廓的所有像素相加而得出的輪廓的總體特征。”

中心矩型-
空間矩:?m00,m10,m01,m20,m11,m02,m30,m21,m12,m03。
中心矩:?mu20,mu11,mu02,mu30,mu21,mu12,mu03。
Hu矩:有七個(gè)Hu矩(h0 — h6)或(h1 — h7),兩種表示法都使用。
我們使用cv2.fitEllipse()計(jì)算矩并將橢圓擬合在這些點(diǎn)上。從輪廓和力矩中得出角度,因?yàn)楦淖冘嚨佬枰?5度旋轉(zhuǎn),這被認(rèn)為是汽車轉(zhuǎn)彎角度的閾值。

現(xiàn)在,我們不僅可以打印檢測(cè)變化的車道,還可以使用Tkinter作為一個(gè)簡(jiǎn)單的彈出窗口來(lái)提醒更改。

使用Greenline測(cè)量角度,并在框架中的汽車上繪制矩形

彈出警報(bào)(作者提供的圖片)

輸出
在本教程中,使用車道變更檢測(cè)方法探索了智能汽車導(dǎo)航的小型演示。計(jì)算機(jī)視覺(jué)正在迅速發(fā)展,其應(yīng)用不僅在汽車的本地導(dǎo)航中而且在火星導(dǎo)航和產(chǎn)品檢查領(lǐng)域中也在不斷發(fā)展,甚至醫(yī)療應(yīng)用也正在開(kāi)發(fā)中,并可以在早期用于檢測(cè)X射線圖像中的癌癥和腫瘤階段。
代碼鏈接:https://github.com/Hitesh-Valecha/Car_Opencv
參考文獻(xiàn):
Bradski, Gary and Kaehler, Adrian,?Learning OpenCV: Computer Vision in C++ with the OpenCV Library, O’Reilly Media, Inc., 2nd edition, 2013, @10.5555/2523356, ISBN — 1449314651.
Laganiere, Robert, OpenCV Computer Vision Application Programming Cookbook, Packt Publishing, 2nd edition, 2014, @10.5555/2692691, ISBN — 1782161481.
交流群
歡迎加入公眾號(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)出群,謝謝理解~
