目標(biāo)追蹤:使用ByteTrack進(jìn)行目標(biāo)檢測(cè)和跟蹤
共 8710字,需瀏覽 18分鐘
·
2024-07-14 10:05
點(diǎn)擊上方“小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
BYTE算法是一種簡(jiǎn)單而有效的關(guān)聯(lián)方法,通過(guò)關(guān)聯(lián)幾乎每個(gè)檢測(cè)框而不僅僅是高分的檢測(cè)框來(lái)跟蹤對(duì)象。這篇博客的目標(biāo)是介紹ByteTrack以及多目標(biāo)跟蹤(MOT)的技術(shù)。我們還將介紹在樣本視頻上使用ByteTrack跟蹤運(yùn)行YOLOv8目標(biāo)檢測(cè)。
多目標(biāo)跟蹤(MOT)
你可能聽(tīng)說(shuō)過(guò)目標(biāo)檢測(cè),有許多算法如Faster RCNN、SSD和YOLO的各個(gè)版本,它們可以以很高的準(zhǔn)確性檢測(cè)物體。但有一個(gè)更新的問(wèn)題是多目標(biāo)跟蹤。基本上,你將傳遞一個(gè)視頻流,對(duì)于每一幀,你需要檢測(cè)對(duì)象并分配一個(gè)“對(duì)象ID”,在下一幀中,如果檢測(cè)到相同的對(duì)象,需要分配相同的對(duì)象ID。有許多用于MOT的算法,如SORT(簡(jiǎn)單在線和實(shí)時(shí)跟蹤)、DeepSort、StrongSort等。
有各種用于目標(biāo)跟蹤的方法,包括:
1. 基于特征的跟蹤:這涉及基于其特征(如顏色、形狀、紋理等)進(jìn)行跟蹤。
2. 模板匹配:正如其名稱所示,該方法使用預(yù)定義的模板在每個(gè)視頻序列中進(jìn)行匹配。
3. 相關(guān)性跟蹤:該方法用于計(jì)算目標(biāo)對(duì)象與后續(xù)幀中候選區(qū)域的相似性。
4. 基于深度學(xué)習(xí)的跟蹤:該方法使用在大型數(shù)據(jù)集上訓(xùn)練的神經(jīng)網(wǎng)絡(luò),以實(shí)時(shí)檢測(cè)和跟蹤對(duì)象。
在你可能對(duì)MOT有了一些基本的了解。讓我們嘗試進(jìn)入ByteTrack并嘗試?yán)斫鉃槭裁此潜菵eepSort等更好的目標(biāo)跟蹤。
ByteSort
首先,我們將了解先前MOT算法的問(wèn)題,然后理解ByteSort的邏輯。
其他MOT算法的問(wèn)題:
低置信度檢測(cè)框:其他MOT算法的第一個(gè)問(wèn)題是刪除低置信度的檢測(cè)框。而B(niǎo)yteTrack考慮了低置信度的檢測(cè)框。為什么呢?
因?yàn)榈椭眯哦鹊臋z測(cè)框有時(shí)表示物體的存在,例如被遮擋的物體。過(guò)濾這些對(duì)象會(huì)在MOT中引入不可逆的錯(cuò)誤,導(dǎo)致不可忽視的漏檢和碎片化的軌跡。讓我們通過(guò)例子來(lái)理解:
Detection boxes
如圖 t1 中所示,我們初始化三個(gè)不同的tracklet,因?yàn)樗鼈兊姆謹(jǐn)?shù)高于0.5。但在 t2 和 t3 中,分?jǐn)?shù)從 0.8 下降到 0.4,然后再下降到 0.1。
Tracklets by associating high scores detection boxes
這些檢測(cè)框?qū)⑼ㄟ^(guò)閾值機(jī)制被消除,紅色軌跡隨之消失,如圖 b 所示。但如果我們考慮所有的檢測(cè)框,將引入更多的假陽(yáng)性,例如圖 a 中最右側(cè)的框。這帶來(lái)了第二個(gè)問(wèn)題:
假陽(yáng)性邊框的考慮:在這里識(shí)別到與tracklets相似性提供了在低分檢測(cè)框中區(qū)分對(duì)象和背景的強(qiáng)關(guān)聯(lián)。
Tracklets by associating every detection boxes
例如,如圖 c 所示,通過(guò)運(yùn)動(dòng)預(yù)測(cè)的框(虛線)將兩個(gè)低分檢測(cè)框與tracklets匹配,從而正確恢復(fù)了對(duì)象。由于背景框沒(méi)有匹配的tracklet,因此將其移除。因此,為了在匹配過(guò)程中使用高分到低分的檢測(cè)框,這種簡(jiǎn)單而有效的關(guān)聯(lián)方法被稱為BYTE,因?yàn)槊總€(gè)檢測(cè)框是tracklet的基本單元。
首先,它根據(jù)運(yùn)動(dòng)或外觀相似性將高分檢測(cè)框與tracklets匹配。然后,它采用卡爾曼濾波器來(lái)預(yù)測(cè)tracklets在下一幀的位置。然后,可以使用IoU或Re-ID特征距離計(jì)算預(yù)測(cè)框與檢測(cè)框之間的相似性。在第二個(gè)匹配步驟中,使用相同的運(yùn)動(dòng)相似性匹配低分檢測(cè)和未匹配的tracklets,即紅框中的tracklets。讓我們嘗試?yán)斫鈹?shù)據(jù)關(guān)聯(lián),這是MOT算法的核心。
數(shù)據(jù)關(guān)聯(lián)
這是多目標(biāo)跟蹤的核心,首先計(jì)算tracklets和檢測(cè)框之間的相似性,并根據(jù)相似性應(yīng)用不同的策略進(jìn)行匹配。
相似性度量:對(duì)于關(guān)聯(lián),位置、運(yùn)動(dòng)和外觀是三個(gè)重要的線索。SORT以非常簡(jiǎn)單的方式使用位置和運(yùn)動(dòng)線索。它采用卡爾曼濾波器來(lái)預(yù)測(cè)下一幀中的tracklets,然后計(jì)算檢測(cè)框和預(yù)測(cè)框之間的IoU作為相似性。但是位置和運(yùn)動(dòng)線索適用于短程匹配。但對(duì)于長(zhǎng)程匹配,外觀相似性是有幫助的。例如,長(zhǎng)時(shí)間被遮擋的對(duì)象將使用外觀相似性進(jìn)行識(shí)別。外觀相似性通過(guò)Re-ID特征的余弦相似度來(lái)計(jì)算。DeepSort使用一個(gè)獨(dú)立的深度學(xué)習(xí)模型進(jìn)行外觀相似性。
匹配策略:在相似性計(jì)算后,匹配策略用于為對(duì)象分配ID。這可以通過(guò)匈牙利算法或貪婪分配來(lái)完成。SORT通過(guò)一次匹配將檢測(cè)框與tracklets匹配。而DeepSort使用級(jí)聯(lián)匹配策略,首先將檢測(cè)框與最近的trackers匹配,然后匹配失去的tracklets。
BYTE算法
(d)BYTETrack的偽代碼。(綠色是該方法的關(guān)鍵)
BYTE算法的輸入是視頻序列和檢測(cè)器。還有一個(gè)檢測(cè)閾值。該算法輸出視頻的軌跡T,每一幀包含對(duì)象的邊界框和ID。對(duì)于視頻中的每一幀,首先使用檢測(cè)器Det預(yù)測(cè)檢測(cè)框和預(yù)測(cè)分?jǐn)?shù)。然后根據(jù)檢測(cè)分?jǐn)?shù)閾值將檢測(cè)框分為Det(high)和Det(low)兩類。
在分離了檢測(cè)框之后,對(duì)每個(gè)軌跡T應(yīng)用卡爾曼濾波器來(lái)預(yù)測(cè)當(dāng)前幀的新位置。首先,在高檢測(cè)框上應(yīng)用關(guān)聯(lián),然后在剩余的低檢測(cè)框上應(yīng)用關(guān)聯(lián)。BYTE的主要亮點(diǎn)是,它非常靈活,可以與不同的關(guān)聯(lián)方法兼容。
性能
ByteTrack優(yōu)于SORT和DeepSORT算法。ByteTrack的MOTA(多目標(biāo)跟蹤準(zhǔn)確性)為76.6,而SORT和DeepSort分別為74.6和75.4。現(xiàn)在,你可能已經(jīng)理解了ByteTrack的主要概念。我想這很簡(jiǎn)單。讓我們嘗試在實(shí)際項(xiàng)目中應(yīng)用它。
使用YOLOv8檢測(cè)器的ByteTrack
在這里,我們將看到如何使用YOLOv8檢測(cè)器跟蹤道路上的車輛,并計(jì)算進(jìn)出的車輛數(shù)。
如你所見(jiàn),每輛新車都被分配了一個(gè)ID、一個(gè)類名和檢測(cè)概率。使用in和out,你可以看到進(jìn)出交通的計(jì)數(shù)。讓我們看看這個(gè)實(shí)現(xiàn)的代碼:
import supervision as svfrom ultralytics import YOLOfrom tqdm import tqdmimport argparseimport numpy as nptracker = sv.ByteTrack()def process_video(source_weights_path: str,source_video_path: str,target_video_path: str,confidence_threshold: float = 0.3,iou_threshold: float = 0.7-> None:model = YOLO(source_weights_path) # Load YOLO modelclasses = list(model.names.values()) # Class namesLINE_STARTS = sv.Point(0,500) # Line start point for count in/out vehicleLINE_END = sv.Point(1280, 500) # Line end point for count in/out vehicletracker = sv.ByteTrack() # Bytetracker instancebox_annotator = sv.BoundingBoxAnnotator() # BondingBox annotator instancelabel_annotator = sv.LabelAnnotator() # Label annotator instanceframe_generator = sv.get_video_frames_generator(source_path=source_video_path) # for generating frames from videovideo_info = sv.VideoInfo.from_video_path(video_path=source_video_path)line_counter = sv.LineZone(start=LINE_STARTS, end = LINE_END)line_annotator = sv.LineZoneAnnotator(thickness=2, text_thickness=2, text_scale= 0.5)with sv.VideoSink(target_path=target_video_path, video_info=video_info) as sink:for frame in tqdm(frame_generator, total= video_info.total_frames):# Getting result from modelresults = model(frame, verbose=False, conf= confidence_threshold, iou = iou_threshold)[0]detections = sv.Detections.from_ultralytics(results) # Getting detections#Filtering classes for car and truck only instead of all COCO classes.detections = detections[np.where((detections.class_id==2)|(detections.class_id==7))]detections = tracker.update_with_detections(detections) # Updating detection to Bytetracker# Annotating detection boxesannotated_frame = box_annotator.annotate(scene = frame.copy(), detections= detections)#Prepare labelslabels = []for index in range(len(detections.class_id)):# creating labels as per required.+ str(detections.tracker_id[index]) + " " + classes[detections.class_id[index]] + " "+ str(round(detections.confidence[index],2)) )# Line counter in/out trigger=detections)# Annotating labelsannotated_label_frame = label_annotator.annotate(scene=annotated_frame, detections=detections, labels=labels)# Annotating line labelsline_annotate_frame = line_annotator.annotate(frame=annotated_label_frame, line_counter=line_counter)= line_annotate_frame)if __name__ == "__main__":parser = argparse.ArgumentParser("video processing with YOLO and ByteTrack")parser.add_argument("--source_weights_path",required=True,help="Path to the source weights file",type=str)parser.add_argument("--source_video_path",required=True,help="Path to the source video file",type = str)parser.add_argument("--target_video_path",required=True,help="Path to the target video file",type= str)parser.add_argument("--confidence_threshold",default = 0.3,help= "Confidence threshold for the model",type=float)parser.add_argument("--iou_threshold",default=0.7,help="Iou threshold for the model",type= float)args = parser.parse_args()process_video(source_weights_path=args.source_weights_path,source_video_path= args.source_video_path,target_video_path=args.target_video_path,confidence_threshold=args.confidence_threshold,iou_threshold=args.iou_threshold)
在這里,我使用了YOLOv8 Ultralytics庫(kù)來(lái)加載在COCO數(shù)據(jù)集上訓(xùn)練的YOLO模型。Supervision庫(kù)用于加載ByteTrack和其他視覺(jué)任務(wù),如標(biāo)注、車輛計(jì)數(shù)等。
你只需通過(guò)傳遞視頻作為輸入運(yùn)行此命令:
python sv_bytetracker_yolo.py --source_weights_path yolov8m.pt --source_video_path test_video.mp4 --target_video_path test_pred.mp4 --confidence_threshold 0.1
如果你想跟蹤其他類別,可以從代碼中刪除類別過(guò)濾器。
應(yīng)用場(chǎng)景
因此,我們已經(jīng)完全了解了ByteTrack。它可以在各種應(yīng)用和行業(yè)中使用,例如:
1. 汽車行業(yè):用于跟蹤道路上的車輛進(jìn)行交通分析,例如任何車輛是否朝錯(cuò)誤的方向行駛,四路口的交通情況等。
2. 生產(chǎn)行業(yè):可以在生產(chǎn)線上用于計(jì)數(shù)和跟蹤生產(chǎn)物品。
3. 購(gòu)物中的客戶互動(dòng):跟蹤客戶的移動(dòng),了解客戶對(duì)哪種產(chǎn)品或哪個(gè)類別更感興趣。他們持有產(chǎn)品的時(shí)間有多長(zhǎng),最終是購(gòu)買還是放回貨架。
4. 增強(qiáng)客戶體驗(yàn):在客戶看起來(lái)困惑或?qū)ふ耶a(chǎn)品時(shí)間過(guò)長(zhǎng)時(shí)進(jìn)行識(shí)別。
總結(jié)
1. 有各種MOT模型,如SORT、DeepSort、ByteTrack等。
2. 有各種用于對(duì)象跟蹤的方法/技術(shù),包括基于特征的跟蹤、模板匹配、相關(guān)性跟蹤和基于深度學(xué)習(xí)的跟蹤。
3. ByteTrack算法考慮了低分檢測(cè)框(與高分檢測(cè)框一起)進(jìn)行對(duì)象跟蹤。
4. 數(shù)據(jù)關(guān)聯(lián)應(yīng)用于每個(gè)檢測(cè)。
5. 在數(shù)據(jù)關(guān)聯(lián)中,生成了tracklet和檢測(cè)框之間的相似性。然后根據(jù)相似性應(yīng)用不同的策略進(jìn)行匹配。
6. 相似性可以通過(guò)IoU或由卡爾曼濾波器的tracklet預(yù)測(cè)的Re-ID計(jì)算。
7. 對(duì)于長(zhǎng)距離,外觀相似性是有用的。
8. 在匹配策略中使用了匈牙利算法。
9.Byte首先對(duì)高分檢測(cè)框應(yīng)用關(guān)聯(lián),然后對(duì)低分檢測(cè)框應(yīng)用關(guān)聯(lián)。
下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺(jué)、目標(biāo)跟蹤、生物視覺(jué)、超分辨率處理等二十多章內(nèi)容。
下載2:Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目52講
在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車道線檢測(cè)、車輛計(jì)數(shù)、添加眼線、車牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺(jué)實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺(jué)。
下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。
交流群
歡迎加入公眾號(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)出群,謝謝理解~
