8.4 目標跟蹤(下)——大橋車流量統計
上一小節,對deepsort的實現步驟進行了詳細分析,本小節將使用deepsort代碼以及yolov5來實現車流量統計。
本節,首先對deepsort原始程式碼的設計進行簡要的結構剖析,來學習代碼設計,然後將其結合yolov5,實現車流量統計。
注意,代碼所需的模型檔,通過網盤下載:連結:https://pan.baidu.com/s/1Ys_v1Tqta4wJMHC8NKeTTg 提取碼:ucf4
注意,ckpt.t7為deepsort的模型檔,一定要放到:F:\pytorch-tutorial-2nd\code\chapter-8\tracking\deep_sort\deep_sort\deep\checkpoint下麵
deepsort源碼——結構分析
deepsort的代碼不算複雜,設計了幾個核心類,然後為各個核心功能編寫了實現函數。這裡繪製簡要的UML圖,對代碼設計的思路進行學習。
對於一個業務場景,首先識別實體,並分析實體的屬性和功能,下面自下而上進行分析目標跟蹤當中存在的實體。
Track目標物體:目標跟蹤的核心元素是目標物體,這裡稱為Track類,對於一個目標,需要有座標資訊,id, 特徵向量清單,狀態等資訊。
Tracker目標跟蹤器:管理所有目標,並可實現目標的更新,因此需要卡爾曼濾波器,管理目標集合tracks等資訊。
KalmanFilter卡爾曼濾波器:維護卡爾曼增益矩陣,並實現預測、更新兩大功能。
DeepSort類:進行統一封裝,對外提供update函數,返回跟蹤框。
對於級聯匹配,會在Tracker類中_match()實現,其中設計了一系列模組,包括
matching_cascade:級聯匹配實現,迴圈70次進行匹配。
min_cost_matching:實現一次最小代價匹配。
linear_assignment:匈牙利演算法實現。
NearestNeighborDistanceMetric:級聯匹配中距離度量功能實現,其中維護了各目標的所有特徵向量,每一幀的特徵向量都會被保存。最大保存100個特徵向量。
if self.budget is not None:
self.samples[target] = self.samples[target][-self.budget:] # 相當巧妙的實現最多記錄最新的100個特徵向量
Copy
到這裡,deepsort大體框架以及搭建完畢,使用方法非常簡單,只需要產生實體DeepSort類,調用.update()即可獲得跟蹤框資訊。
deepsort+yolov5——車流量統計
目標跟蹤可以獲得目標的位置及唯一標識,它只是方法,並不是目的。
基於目標跟蹤方法,可以實現許多有價值的事情,例如卡口人流量計數,交通道路車流量計數與統計,警戒區域預警等。
進行行人計數或車流量計數時,需要判斷目標是否經過特定區域,這時需要撞線機制來實現,撞線機制可以有兩種方法實現。
一種是基於區域判斷,另外一種是基於線段相交判斷。
另外一種是基於線段相交判斷,則是基於物體的歷史軌跡曲線,判斷是否與界線相交。
計數中的撞線機制
本案例採用基於區域的撞線機制,對邊界設置兩個區域,一般稱inner和outter區域,當物體先到達inner,再進入outter,則可判斷物體是離開,反之亦然。
對於inner和outter區域,每個區域需要記錄曾經到達區域裡的目標id,僅當兩個區域同時存在過目標id,可以計數,並且刪除目標id。
例如圖中的ID-60,進入了inner區域(藍色),inner區域需要觀察ID-60是否存在outer區域中(黃色),當前是不存在的,因此添加到inner區域的歷史清單中。
下一幀,ID-60到達黃色區域,黃色區域同樣地,先判斷ID-60是否來自藍色區域,它在藍色區域的歷史記錄中找到了ID-60,因此可以判斷ID-60是從inner到達outer,所以outer進行加一。
反之inter加一。
在代碼實現上有一些抽象,這裡做簡單的講解。
如何判斷物體到達inner和outter區域?
採用mask矩陣,inner區域圖元是1, outer圖元是2,mask矩陣大小與圖片大小一致,採用目標的位置座標對mask矩陣索引,通過索引值==1? 還是==2?來判斷當前物體位於什麼區域。
如何判斷物體先、後順序?
區域中發現新物體時,首先判斷是否存在對向區域,若不存在,才可以加入區域的物體容器中進行管理。若存在,即可刪除,並且計數。
為了實現撞線機制,這裡設計了三個類,分別是BoundaryType、CountBoundary和BaseCounter
處理邏輯在BaseCounter的counting(),邊界區域抽象成CountBoundary,實現了必要的函數來完成計數。
下面簡單介紹counting函數中,如何判斷物體是從outer來,到達inter,實現inter計數+1的(反之亦然)
第1行:通過物體的x,y座標,對索引矩陣進行索引,得到索引值。例如:[1, 2, 0, 0, 0, ...]。通過索引值可知在何區域
第4行:通過索引值清單,判斷當前在inner區域的目標,並且返回它們的id
第5行:獲取,當前到過outer的目標id
第8行:判斷是否有交集,有交集資料表明,該id從outer來,已經抵達inner。可以計數。
第9行:判斷是否存在差集,inner有,outer沒有,表明物體可以加入inner的id_container中進行管理
第10行:由於目標完成了計數,outer_boundary中需要刪除它。
第11行:由於目標第一次到來,所以註冊到inner_boundary中,後續供outer_boundary查詢。
bbox_area_list = self.area_mask[index_xy] # 獲取bbox在圖像中區域的索引,1,2分別表示在邊界區域. [int,]
# ======================== 先處理inner區域 ====================================
inner_tracks_currently_ids = self.get_currently_ids_by_area(tracks, bbox_area_list, BoundaryType.inner)
outer_tracks_history_ids = list(self.outer_boundary.id_container.keys()) # 獲取歷史幀經過outer區域的目標的id
# 當前與歷史的交集,認為是目標從outer已經到達inner,可以計數,並且刪除。
outer_2_inner_tracks_id = self.intersection(inner_tracks_currently_ids, outer_tracks_history_ids)
only_at_inner_tracks_id = self.difference(inner_tracks_currently_ids, outer_tracks_history_ids)
self.outer_boundary.remove_tracks(outer_2_inner_tracks_id) # 刪除outer中已計數的id
self.inner_boundary.register_tracks(only_at_inner_tracks_id) # 註冊僅inner有的id
Copy
注意事項:
在第1行中 self.area_mask的製作中,由於採用的是圖元1和2,在resize時,導致2的邊界有一系列1的存在,導致了誤檢!
按設計,1在2的下面,這裡1反而出現在了2的上面,導致實際是“出”的,計算為了“入”
把上述代碼組裝起來得到01-main.py,做好模型檔、視頻檔、邊界點的配置,運行即可得到以下結果。
模型權重檔,視頻檔可通過網盤下載:
注意,ckpt.t7為deepsort的模型檔,一定要放到:F:\pytorch-tutorial-2nd\code\chapter-8\tracking\deep_sort\deep_sort\deep\checkpoint下麵
完整視頻可見B站
這裡為了實現邊界區域點集的獲取,編寫了滑鼠點選邊界區域的代碼00-draw-border.py。
運行後,滑鼠按兩下實現選點,選點順序必須從左上角開始,順時針,選擇完畢,terminal中列印的點集list,複製下來使用即可。
小結
目標跟蹤案例中,內容比較多,這裡總結一些關鍵知識點:
- SORT與DeepSORT演算法步驟:本案介紹目標跟蹤中出現的問題,一步步引出DeepSORT設計的複雜邏輯,由問題出發,以解決問題的方式,觀察DeepSORT的步驟。
- DeepSORT中的核心演算法:卡爾曼濾波器與匈牙利演算法,卡爾曼濾波常用于帶有高斯雜訊的線性運動系統,可以很好的預測運動狀態。匈牙利演算法可以解決二分圖匹配問題,今後也可以借鑒兩個演算法解決實際業務問題。
- DeepSORT代碼結構剖析:通過UML圖,分析DeepSORT代碼是如何抽象、設計的,鞏固物件導向程式設計的思想。
- 計數的撞線機制:介紹基於區域的撞線機制,並通過物件導向程式設計來實現計數器。
- DeepSORT+YOLOv5的聯合使用:將目標檢測+目標跟蹤+計數機制聯合使用,構建實際應用,在主代碼中可以發現,各功能模組抽象獨立出去,主代碼的核心代碼僅兩行:bboxes = detector.detect(im); counter.counting(list_bboxs);
目標跟蹤仍是一個較大研究方向,DeepSORT僅是其中一種方法,要深入掌握目標跟蹤還需學習其他方法。
留言列表