【CV】使用OpenCV搭建违章停车检测系统
各位小伙伴大家好,今天將會帶領大家一起學習如何搭建一個違章停車檢測系統。需要重點說明的是,今天使用的邏輯和判定條件比較難,尤其是他的編程實現。不過小伙伴不要怕,我們提供了項目的開源代碼,具體鏈接如下:
https://github.com/hasantha-nirmal/Traffic_Violation_Detection_Yolov4_Deep-Sort
接下來我們將詳細介紹如何實現這個系統
首先,我們需要簡要了解一下這個項目中的停車違章檢測是什么意思。為了介紹方便,我們將穿插使用學術術語和生活用語。想象一下,我們有一個感興趣的區域也可以稱為某個地方,車輛不應該停放在那里。但是,如果車輛只是停在那里一會兒,我們也不能將其是為為違章,例如馬路邊允許臨時停車的區域。如果我們正在談論的這個區域離道路太近,那么經過的車輛可能會與這個感興趣的區域相交,并且會立即被視為違章。所以首先,我們必須消除這種情況。也就是首先解決臨時停車不會判定為違章的情況。最簡單的解決方案是為每輛單獨的車輛引入計時器。由此,我們可以確保車輛已經在該限制區域內停留了多長時間。
采用感興趣區域作為停車位,我們只需使用一個攝像頭即可,同時這個攝像頭不僅可以同時監控和檢測特定車輛占用該停車位的時間,還可以計算出每輛車必須支付的費用停車場。當然了,這需要額外的開發,這里小白做過多的介紹
我們前面說過,我們需要建立一個計時器。這個任務的難點是需要考慮許多車輛肯定會同時出現,這使得任務變得比較復雜。不過也沒有關系,我們只需要為不同的車輛設置不同的計時器即可。
接下來我們將詳細介紹如何通過代碼實現上述的功能。
上面的代碼給出了我們如何選擇停車位作為我們的感興趣區域。我們首先定義了一個名為park_co的空白數組,之后創建了一個于圖像分辨率具有相同高度或者相同寬度的一個權威零的數組。之后選擇感興趣區域的頂點坐標。在pts變量中存放我們選擇的感興趣區域的頂點坐標。之后我們使用OpenCV中的fillPoly函數將感興趣區域填充上,以便于我們判斷車輛是否與感興趣區域相交。
感興趣區域的選擇如下圖所示
現在,我們有了感興趣的區域或禁止車輛停放的地方的像素的所有坐標點。然后我們選取車輛的邊界框坐標(如何識別車輛呢,可以參考小白之前的文章)。但是,這又帶來了一個問題。如果相機離這個感興趣區域太近,當有車輛接近該區域時,它的邊界框會占據非常多的坐標點,當同時有車輛時,必須對視頻的每一幀重復這個過程,導致幀率急劇下降。所以,我對這個案例提出了一個假設:如果一個車輛/邊界框與這個 ROI 相交,它肯定也與邊界框的底線相交。所以就像在車道線違例中一樣,而不是取車輛的所有邊界框坐標
bbox_bottom_line_co = list(zip(*line(*(int(bbox[0])+50,int(bbox[3])), *(int(bbox[2])-50,int(bbox[3])))))上面是提取底線坐標的代碼。我們通過從線條的每一側移除 50 個像素坐標來減少線條長度,以便更好地表示車輛。因此,該線始終停留在車輛區域內,并且不占用其周圍的任何空閑空間。
if len(intersection(parking_co, bbox_bottom_line_co)) > 0: frame_matrix.append((str(frame_num) + class_name + str(t), ( str(int(bbox[0])).zfill(4), str(int(bbox[1])).zfill(4), str(int(bbox[2])).zfill(4), str(int(bbox[3])).zfill(4))))想象一輛車第一次與該地區相交。當它發生在特定幀內的那一刻,我們立即附加該事件的幀號frame_num車輛類型(class_name),車輛跟蹤 ID(str(t))和該車輛在該幀的邊界框坐標
chk_index = str(frame_matrix).find(str(frame_num — 1) + class_name + str(t))然后立即檢查前一幀是否為同一車輛發生了相同類型的相交點。如果這個相交點是第一次發生,則不滿足這個條件,程序進入下一幀,沒有任何進一步的交互。但是想象一下,如果這是車輛與感興趣區域相交后的第二幀,那么會為這個chk_index變量賦一個值。
if bool(chk_index + 1) == True: previous_bbox_co_str = str(frame_matrix)[ (chk_index — 1) + len(str(frame_num — 1)) + len(class_name + str(t)) + 5:(chk_index — 1) + len(str(frame_num — 1)) + len(class_name + str(t)) + 5 + 30]我們首先對( chk_index+1 )的布爾值給出一個正值。設置為1的原因是,對于特定車輛,它的日志詳細信息可能從數組的最開頭開始,因此將其在數組中的放置值設置為 0。如果發生這種情況,bool(0)會使條件為 false即使它為真。如果沒有這樣的日志條目,則 chk_index僅返回 -1,當設為?+1 時,它會給出所需的 False 輸出。
此外,當該條件為真時,將會有關于邊界框的前一幀日志詳細信息獲取到另一個名為previous_bbox_co_str的變量中。
現在我們知道了車輛在當前幀和前一幀的邊界框坐標。由于我們一直都知道車輛一直在 ROI 中,因此我們需要確定車輛是靜止(不動)還是移動的。這里我們聲明了一個名為immobile的新函數,用于實現這個功能。
# Check the immobility of vehicle #line 99 def immobile(bbox, previous_bbox_str): previous_bbox0 = int(previous_bbox_str[1:5]) previous_bbox1 = int(previous_bbox_str[9:13]) previous_bbox2 = int(previous_bbox_str[17:21]) previous_bbox3 = int(previous_bbox_str[25:29])total = abs(bbox[0] — previous_bbox0) + abs(bbox[1] — previous_bbox1) + abs(bbox[2] — previous_bbox2) + abs( bbox[3] — previous_bbox3) if total <= 4: return True else: return False這里我們使用了previous_bbox_co_str作為函數的屬性,以及當前的邊界框坐標。我們分別計算xmin、ymin、xmax 和 ymax 值的差值,如果絕對差值小于 4,輸出 True,表示車輛是不動的,否則輸出 False。
需要注意,即使車輛或任何物體完全停止,YOLO 也會給出波動的邊界框坐標。為避免這個現象并使此過程穩健,我們在此處將判定變量設置為比較高的值。該值越高,程序對邊界框的隨機波動就越魯棒。
因此,如果作為車輛的函數輸出是不動的(靜止的),那么我們需要立即檢查 cache_matrix 中是否有任何先前記錄的條目,如果沒有,我們需要加上當前時間(t_start)和車輛類型(class_name)并跟蹤標識(str(t))
if str((class_name + str(t))) not in str(cache_matrix): #line 310 t_start = datetime.now() cache_matrix.append((str(t_start), class_name + str(t))) print(cache_matrix)之后,我們檢查車輛是否在cache_matrix中。同時還要檢查同一輛車是否也在viol_matrix中。(因為我已經將違規車輛記錄,這些車輛已經靜止并超過了時間限制)。如果不是,我們應立即檢索該特定車輛的t_start值并使用當前時間檢查不同的時間。
index = (str(cache_matrix).find(str((class_name + str(t))))) #line 318 t_start_cm = str(cache_matrix)[index — 28:index — 11] t_spending = (datetime.now() — datetime.strptime(t_start_cm, ‘%y-%m-%d %H:%M:%S’)).total_seconds()如果時間差 (t_spending) 超過時間限制,那么我們將詳細信息記錄到電子表格中,其中包括車輛第一次進入時間 (t_start_cm)、車輛類型 (class_name) 和車輛跟蹤 ID (str(t)) . 在這種情況下,出于演示目的,我們將計時器設置為 10 秒。示例如下
sheet.write(row_num, 0, str(t_start_cm), style) #line 328 # sheet.write(row_num, 1, str(round(t_spending, 2)), style) sheet.write(row_num, 1, str(class_name ) + str(t), style) row_num += 1 workbook.save('outputs/xlsx/parking/details.xls')然后我們必須將這輛特定車輛作為日志條目放入viol_matrix數組中,因為該車輛現在已經違規了。這避免了進一步的重復和錯誤的日志條目。然后,我們可以拍攝該違規車輛的圖像并將其保存為車輛類型,并將跟蹤 ID 作為其名稱。
viol_matrix.append((str((class_name + str(t))))) #line 334 # print(t_start_cm, t_spending, datetime.now()) cropped = image.crop((int(bbox[0]), int (bbox[1]), int(bbox[2]), int(bbox[3]))) cropped.save( 'outputs/caps_of_detections/parking/' + str( class_name) + str(t) + str(' .jpg'))以上基本上是我們設計的違章停車檢測系統的想法。為避免frame_matrix的內存過載,每超過107 個條目使用以下函數刷新該數組。
#Avoid buffer overflow #line 353 if len(frame_matrix)>10?: frame_matrix=[]以上就是本文的全部內容啦,感興趣的小伙伴們可以操練其來了!
往期精彩回顧適合初學者入門人工智能的路線及資料下載(圖文+視頻)機器學習入門系列下載中國大學慕課《機器學習》(黃海廣主講)機器學習及深度學習筆記等資料打印《統計學習方法》的代碼復現專輯 AI基礎下載機器學習交流qq群955171419,加入微信群請掃碼:總結
以上是生活随笔為你收集整理的【CV】使用OpenCV搭建违章停车检测系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: websocket学习总结记录
- 下一篇: android显示圆圈动画,Androi