[AI開發(fā)]基于深度學(xué)習(xí)的視頻多目標(biāo)跟蹤實(shí)現(xiàn)
多目標(biāo)跟蹤大概有兩種方式:
Option1
基于初始化幀的跟蹤,在視頻***幀中選擇你的目標(biāo),之后交給跟蹤算法去實(shí)現(xiàn)目標(biāo)的跟蹤。這種方式基本上只能跟蹤你***幀選中的目標(biāo),如果后續(xù)幀中出現(xiàn)了新的物體目標(biāo),算法是跟蹤不到的。這種方式的優(yōu)點(diǎn)是速度相對(duì)較快。缺點(diǎn)很明顯,不能跟蹤新出現(xiàn)的目標(biāo)。
Option2
基于目標(biāo)檢測(cè)的跟蹤,在視頻每幀中先檢測(cè)出來所有感興趣的目標(biāo)物體,然后將其與前一幀中檢測(cè)出來的目標(biāo)進(jìn)行關(guān)聯(lián)來實(shí)現(xiàn)跟蹤的效果。這種方式的優(yōu)點(diǎn)是可以在整個(gè)視頻中跟蹤隨時(shí)出現(xiàn)的新目標(biāo),當(dāng)然這種方式要求你前提得有一個(gè)好的“目標(biāo)檢測(cè)”算法。
本文主要講述Option2的實(shí)現(xiàn)原理,也就是Tracking By Detecting的跟蹤方式。這篇文章沒有源碼鏈接,關(guān)于“目標(biāo)檢測(cè)”算法的源碼可以參見我上一篇文章,至于“軌跡跟蹤”算法的源碼實(shí)現(xiàn)很簡(jiǎn)單,看完本文相信大家都能寫出來,Python實(shí)現(xiàn)大概200行不到。
Tracking By Detecting的跟蹤過程
Step1:使用目標(biāo)檢測(cè)算法將每幀中感興趣的目標(biāo)檢測(cè)出來,得到對(duì)應(yīng)的(位置坐標(biāo), 分類, 可信度),假設(shè)檢測(cè)到的目標(biāo)數(shù)量為M;
Step2:通過某種方式將Step1中的檢測(cè)結(jié)果與上一幀中的檢測(cè)目標(biāo)(假設(shè)上一幀檢測(cè)目標(biāo)數(shù)量為N)一一關(guān)聯(lián)起來。換句話說,就是在M*N個(gè)Pair中找出最像似的Pair。
對(duì)于Step2中的“某種方式”,其實(shí)有多種方式可以實(shí)現(xiàn)目標(biāo)的關(guān)聯(lián),比如常見的計(jì)算兩幀中兩個(gè)目標(biāo)之間的歐幾里得距離(平面兩點(diǎn)之間的直線距離),距離最短就認(rèn)為是同一個(gè)目標(biāo),然后通過匈牙利算法找出最匹配的Pair。當(dāng)讓,你還可以加上其他的判斷條件,比如我用到的IOU,計(jì)算兩個(gè)目標(biāo)Box(位置大小方框)的交并比,該值越接近1就代表是同一個(gè)目標(biāo)。還有其他的比如判斷兩個(gè)目標(biāo)的外觀是否相似,這就需要用到一種外觀模型去做比較了,可能耗時(shí)更長(zhǎng)。
在關(guān)聯(lián)的過程中,會(huì)出現(xiàn)三種情況:
1)在上一幀中的N個(gè)目標(biāo)中找到了本次檢測(cè)到的目標(biāo),說明正常跟蹤到了;
2)在上一幀中的N個(gè)目標(biāo)中沒有找到本次檢測(cè)到的目標(biāo),說明這個(gè)目標(biāo)是這一幀中新出現(xiàn)的,所以我們需要把它記錄下來,用于下下一次的跟蹤關(guān)聯(lián);
3)在上一幀中存在某個(gè)目標(biāo),這一幀中并沒有與之關(guān)聯(lián)的目標(biāo),那么說明該目標(biāo)可能從視野中消失了,我們需要將其移除。(注意這里的可能,因?yàn)橛锌赡苡捎跈z測(cè)誤差,在這一幀中該目標(biāo)并沒有被檢測(cè)到)
存在的問題
上面提到的跟蹤方法在正常情況下都能夠很好的工作,但是如果視頻中目標(biāo)運(yùn)動(dòng)得很快,前后兩幀中同一個(gè)目標(biāo)運(yùn)動(dòng)的距離很遠(yuǎn),那么這種跟蹤方式就會(huì)出現(xiàn)問題。
如上圖,實(shí)線框表示目標(biāo)在***幀的位置,虛線框表示目標(biāo)在第二幀的位置。當(dāng)目標(biāo)運(yùn)行速度比較慢的時(shí)候,通過之前的跟蹤方式可以很準(zhǔn)確的關(guān)聯(lián)(A, A’)和(B, B’)。但是當(dāng)目標(biāo)運(yùn)行速度很快(或者隔幀檢測(cè))時(shí),在第二幀中,A就會(huì)運(yùn)動(dòng)到***幀中B的位置,而B則運(yùn)動(dòng)到其他位置。這個(gè)時(shí)候使用上面的關(guān)聯(lián)方法就會(huì)得到錯(cuò)誤的結(jié)果。
那么怎樣才能更加準(zhǔn)確地進(jìn)行跟蹤呢?
基于軌跡預(yù)測(cè)的跟蹤方式
既然通過第二幀的位置與***幀的位置進(jìn)行對(duì)比關(guān)聯(lián)會(huì)出現(xiàn)誤差,那么我們可以想辦法在對(duì)比之前,先預(yù)測(cè)目標(biāo)的下一幀會(huì)出現(xiàn)的位置,然后與該預(yù)測(cè)的位置來進(jìn)行對(duì)比關(guān)聯(lián)。這樣的話,只要預(yù)測(cè)足夠精確,那么幾乎不會(huì)出現(xiàn)前面提到的由于速度太快而存在的誤差。
如上圖,我們?cè)趯?duì)比關(guān)聯(lián)之前,先預(yù)測(cè)出A和B在下一幀中的位置,然后再使用實(shí)際的檢測(cè)位置與預(yù)測(cè)的位置進(jìn)行對(duì)比關(guān)聯(lián),可以***地解決上面提到的問題。理論上,不管目標(biāo)速度多么快,都能關(guān)聯(lián)上。那么問題來了,怎么預(yù)測(cè)目標(biāo)在下一幀的位置?
方法有很多,可以使用卡爾曼濾波來根據(jù)目標(biāo)前面幾幀的軌跡來預(yù)測(cè)它下一幀的位置,還可以使用自己擬合出來的函數(shù)來預(yù)測(cè)下一幀的位置。實(shí)際過程中,我是使用擬合函數(shù)來預(yù)測(cè)目標(biāo)在下一幀中的位置。
如上圖,通過前面6幀的位置,我可以擬合出來一條(T->XY)的曲線(注意不是圖中的直線),然后預(yù)測(cè)目標(biāo)在T+1幀的位置。具體實(shí)現(xiàn)很簡(jiǎn)單,Python中的numpy庫(kù)中有類似功能的方法。
仍然存在的不足
即使如此***了,還是存在不足。
軌跡預(yù)測(cè)的前提是需要知道目標(biāo)前面若干幀的軌跡信息,因此在剛開始,目標(biāo)的軌跡是預(yù)測(cè)不到的,或者說預(yù)測(cè)得不準(zhǔn)。所以在剛開始的幾幀,我們還是需要使用原來的方式進(jìn)行對(duì)比關(guān)聯(lián)。