境單目標(biāo)跟蹤器實(shí)戰(zhàn)解析)
簡(jiǎn)介基于卡爾曼濾波的遮擋與重疊環(huán)境下的單目標(biāo)跟蹤器是一份面向計(jì)算機(jī)視覺(jué)與目標(biāo)跟蹤學(xué)習(xí)者的算法工程資源解決復(fù)雜場(chǎng)景下目標(biāo)被遮擋或互相重疊時(shí)容易跟丟的問(wèn)題。資源包共338個(gè)文件以txt標(biāo)簽數(shù)據(jù)、Python腳本、pyc編譯文件及xml配置為主另含一個(gè)mp4測(cè)試視頻壓縮包約25.87MB核心代碼Kalman_Tracker.py實(shí)現(xiàn)濾波預(yù)測(cè)與更新utils.py提供IOU計(jì)算等輔助工具適合入門到進(jìn)階的開(kāi)發(fā)者研讀。已有509人學(xué)習(xí)下載可用于復(fù)現(xiàn)卡爾曼濾波結(jié)合最大IOU匹配的跟蹤流程并通過(guò)TestVideo和labels目錄直觀驗(yàn)證算法在遮擋、重疊場(chǎng)景下的表現(xiàn)。整體結(jié)構(gòu)清晰從數(shù)據(jù)標(biāo)注到算法實(shí)現(xiàn)均有覆蓋是理解目標(biāo)跟蹤中狀態(tài)估計(jì)與數(shù)據(jù)關(guān)聯(lián)的實(shí)用參考。1. 基于卡爾曼濾波的遮擋與重疊環(huán)境下的單目標(biāo)跟蹤器到底難在哪做視覺(jué)跟蹤的人大多有個(gè)共識(shí)單目標(biāo)跟蹤器最怕的從來(lái)不是目標(biāo)跑得快而是目標(biāo)被擋一下、或者兩個(gè)目標(biāo)擦肩而過(guò)??柭鼮V波算法在這類場(chǎng)景里之所以被反復(fù)提起是因?yàn)楦櫰鱽G失目標(biāo)的根因往往不在外觀模型而在狀態(tài)預(yù)測(cè)與觀測(cè)更新之間的脫節(jié)。本文要講的就是一套基于卡爾曼濾波的遮擋與重疊環(huán)境下的單目標(biāo)跟蹤器它解決的問(wèn)題很具體目標(biāo)暫時(shí)看不見(jiàn)時(shí)濾波器靠運(yùn)動(dòng)模型續(xù)命兩個(gè)目標(biāo)重疊時(shí)濾波器靠測(cè)量噪聲和門控機(jī)制區(qū)分主目標(biāo)。適合的人群是已經(jīng)在用檢測(cè)器或相關(guān)濾波類跟蹤器、但卡在遮擋魯棒性上的從業(yè)者如果你正準(zhǔn)備把單目標(biāo)跟蹤器從干凈場(chǎng)景往復(fù)雜場(chǎng)景遷移這篇筆記能把原理、參數(shù)和踩坑點(diǎn)一次講透。2. 為什么遮擋和重疊會(huì)打穿普通跟蹤器卡爾曼濾波在這里補(bǔ)什么普通的IoU跟蹤器或者基于外觀的跟蹤器在目標(biāo)可見(jiàn)時(shí)表現(xiàn)很好一旦目標(biāo)被路牌、行人、車輛遮擋超過(guò)幾幀外觀模型拿不到穩(wěn)定輸入跟蹤框就開(kāi)始漂移。更麻煩的是兩個(gè)目標(biāo)重疊時(shí)檢測(cè)框合并、特征混淆跟蹤器不知道當(dāng)前檢測(cè)框到底屬于誰(shuí)。要理解卡爾曼濾波算法為什么能補(bǔ)這個(gè)洞得先把跟蹤問(wèn)題拆成兩個(gè)步驟預(yù)測(cè)和更新。2.1 卡爾曼濾波在單目標(biāo)跟蹤器里管的是運(yùn)動(dòng)狀態(tài)不是外觀卡爾曼濾波本質(zhì)是一個(gè)遞歸的狀態(tài)估計(jì)器。它假設(shè)系統(tǒng)狀態(tài)服從高斯分布用狀態(tài)轉(zhuǎn)移矩陣描述目標(biāo)怎么動(dòng)用觀測(cè)矩陣描述測(cè)量值怎么映射到狀態(tài)空間。在單目標(biāo)跟蹤器里狀態(tài)量通常取目標(biāo)框的中心坐標(biāo)、寬高以及對(duì)應(yīng)的速度分量狀態(tài)轉(zhuǎn)移矩陣用勻速模型或者勻加速模型。外觀模型負(fù)責(zé)回答“這是不是目標(biāo)”卡爾曼濾波負(fù)責(zé)回答“目標(biāo)下一幀大概在哪”。兩者分工明確但真正讓遮擋場(chǎng)景變得可控的是卡爾曼濾波的預(yù)測(cè)步驟即使某一幀沒(méi)有觀測(cè)濾波器依然能輸出一個(gè)帶有不確定性的預(yù)測(cè)位置。這個(gè)特性在遮擋場(chǎng)景里非常關(guān)鍵。常見(jiàn)的跟蹤器在目標(biāo)消失后往往直接丟掉目標(biāo)或者停在最后一幀位置而卡爾曼濾波會(huì)用運(yùn)動(dòng)模型繼續(xù)外推同時(shí)協(xié)方差矩陣會(huì)隨著預(yù)測(cè)步數(shù)的增加而增大表示“不確定度在上升”。這種不確定性表達(dá)給了后續(xù)重檢測(cè)一個(gè)搜索范圍而不是憑空去找目標(biāo)。2.2 重疊場(chǎng)景為什么會(huì)讓卡爾曼濾波也翻車卡爾曼濾波算法擅長(zhǎng)處理觀測(cè)噪聲但它有一個(gè)隱含前提觀測(cè)值必須來(lái)自目標(biāo)本身。兩個(gè)目標(biāo)重疊時(shí)檢測(cè)器輸出的框可能是兩者的合并框這個(gè)合并框既不是目標(biāo)A的準(zhǔn)確位置也不是目標(biāo)B的位置而是兩個(gè)高斯分布的混合。把這樣的觀測(cè)直接送進(jìn)濾波器狀態(tài)更新會(huì)被拉向一個(gè)不存在的位置協(xié)方差還可能因?yàn)椤昂孟裼杏^測(cè)”而錯(cuò)誤地縮小導(dǎo)致后續(xù)跟蹤愈發(fā)自信地偏離真實(shí)目標(biāo)。所以基于卡爾曼濾波的遮擋與重疊環(huán)境下的單目標(biāo)跟蹤器重點(diǎn)不在濾波公式本身而在觀測(cè)入口的設(shè)計(jì)。常見(jiàn)做法是引入檢測(cè)置信度作為觀測(cè)質(zhì)量的開(kāi)關(guān)置信度高才做完整更新置信度低只做預(yù)測(cè)不做更新或者用衰減權(quán)重更新。另一個(gè)做法是計(jì)算預(yù)測(cè)框和檢測(cè)框的IoU只有IoU超過(guò)門限才認(rèn)為是有效觀測(cè)否則視為遮擋狀態(tài)保留預(yù)測(cè)結(jié)果。這里有一個(gè)參數(shù)很關(guān)鍵觀測(cè)噪聲協(xié)方差矩陣R。R設(shè)得太小濾波器會(huì)過(guò)度相信觀測(cè)值重疊時(shí)合并框會(huì)瞬間帶偏軌跡R設(shè)得太大濾波器幾乎不更新跟蹤框會(huì)滯后于真實(shí)目標(biāo)。我一般會(huì)按檢測(cè)器的平均定位誤差來(lái)設(shè)R比如檢測(cè)框中心定位的標(biāo)準(zhǔn)差是2個(gè)像素R對(duì)角線就取4左右而不是隨意給個(gè)0.1。2.3 單目標(biāo)跟蹤器與多目標(biāo)跟蹤器的本質(zhì)差異很多人會(huì)把單目標(biāo)跟蹤器和多目標(biāo)跟蹤器搞混實(shí)際兩者的狀態(tài)管理邏輯完全不同。多目標(biāo)跟蹤器需要維護(hù)多個(gè)卡爾曼濾波器實(shí)例每個(gè)目標(biāo)一個(gè)狀態(tài)向量還要額外解決數(shù)據(jù)關(guān)聯(lián)問(wèn)題也就是檢測(cè)框和軌跡之間的匹配。單目標(biāo)跟蹤器只需要維護(hù)一個(gè)狀態(tài)向量但正因?yàn)橹挥幸粋€(gè)目標(biāo)它對(duì)觀測(cè)質(zhì)量反而更敏感因?yàn)闆](méi)有任何冗余目標(biāo)可以糾正錯(cuò)誤。在遮擋與重疊環(huán)境下單目標(biāo)跟蹤器有一個(gè)多目標(biāo)跟蹤器沒(méi)有的優(yōu)勢(shì)不需要做全局最優(yōu)匹配。目標(biāo)重疊時(shí)多目標(biāo)跟蹤器要考慮兩個(gè)軌跡和兩個(gè)檢測(cè)框之間的排列組合而單目標(biāo)跟蹤器只需要判斷當(dāng)前檢測(cè)框和預(yù)測(cè)框是否一致。這個(gè)判斷可以通過(guò)馬氏距離或者IoU門控來(lái)完成邏輯簡(jiǎn)單但效果非常依賴卡爾曼濾波的協(xié)方差預(yù)測(cè)是否合理。協(xié)方差預(yù)測(cè)偏小門控范圍就太小目標(biāo)稍微動(dòng)得快一點(diǎn)就跟丟了協(xié)方差預(yù)測(cè)偏大門控范圍太大重疊目標(biāo)就會(huì)被錯(cuò)誤吞進(jìn)來(lái)。因此我會(huì)特別強(qiáng)調(diào)狀態(tài)轉(zhuǎn)移矩陣中的過(guò)程噪聲Q的設(shè)計(jì)。Q體現(xiàn)了“我們有多相信運(yùn)動(dòng)模型”它決定協(xié)方差預(yù)測(cè)的增長(zhǎng)速度。對(duì)于行人這種機(jī)動(dòng)性較強(qiáng)的目標(biāo)Q應(yīng)該設(shè)得大一些對(duì)于車輛這種運(yùn)動(dòng)相對(duì)平滑的目標(biāo)Q可以小一些。具體數(shù)值通常在調(diào)參時(shí)按經(jīng)驗(yàn)縮放單位矩陣有的是0.01量級(jí)有的是0.1量級(jí)需要根據(jù)視頻幀率和目標(biāo)機(jī)動(dòng)幅度折算。3. 把卡爾曼濾波跟蹤器搭起來(lái)狀態(tài)向量、參數(shù)初始化與最小可運(yùn)行實(shí)現(xiàn)這一章進(jìn)入可復(fù)現(xiàn)環(huán)節(jié)。我會(huì)用一個(gè)Python實(shí)現(xiàn)的最小跟蹤器來(lái)演示完整流程狀態(tài)向量采用[x, y, w, h, vx, vy]六維其中x、y是目標(biāo)框中心坐標(biāo)w、h是寬高vx、vy是對(duì)應(yīng)的速度分量。為什么取六維而不是四維因?yàn)樗俣确至康募尤肽茏尀V波器在遮擋期間保持對(duì)目標(biāo)移動(dòng)趨勢(shì)的估計(jì)如果只有位置和尺寸遮擋期間目標(biāo)只能原地不動(dòng)或勻速直行。3.1 狀態(tài)轉(zhuǎn)移矩陣與過(guò)程噪聲的參數(shù)設(shè)計(jì)勻速模型的離散化狀態(tài)轉(zhuǎn)移矩陣F為F [[1, 0, 0, 0, dt, 0], [0, 1, 0, 0, 0, dt], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]]寬高方向上沒(méi)有速度項(xiàng)因?yàn)閷?shí)際場(chǎng)景里目標(biāo)框的尺寸變化通常是緩慢的強(qiáng)行加速度項(xiàng)反而會(huì)讓遮擋期間框的尺寸發(fā)散。dt是幀間隔時(shí)間通常取1這時(shí)F矩陣會(huì)簡(jiǎn)化為單位矩陣加上速度耦合項(xiàng)。觀測(cè)矩陣H則比較簡(jiǎn)單它只提取前四維位置和尺寸H [[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0]]過(guò)程噪聲矩陣Q我一般按 0.1 * dt 的縮放系數(shù)再疊加到速度分量對(duì)應(yīng)的對(duì)角線元素上具體形式是構(gòu)造一個(gè)6x6矩陣其中位置相關(guān)噪聲取較小值速度相關(guān)噪聲取較大值反映“位置估計(jì)比較可靠、速度估計(jì)存在機(jī)動(dòng)擾動(dòng)”的物理事實(shí)。用代碼表示就是這樣import numpy as np def make_F(dt1.0): F np.eye(6) F[0, 4] dt F[1, 5] dt return F def make_Q(dt1.0, std_acc0.5, std_pos0.01): q_pos std_pos ** 2 q_vel (std_acc * dt) ** 2 Q np.zeros((6, 6)) Q[0, 0] q_pos Q[1, 1] q_pos Q[2, 2] q_pos Q[3, 3] q_pos Q[4, 4] q_vel Q[5, 5] q_vel return Q代碼里std_acc是目標(biāo)機(jī)動(dòng)性的標(biāo)準(zhǔn)差單位是像素每幀平方它的物理含義是目標(biāo)加速度的統(tǒng)計(jì)大小。std_pos則描述位置噪聲的微小擾動(dòng)。這里把Q簡(jiǎn)化成對(duì)角矩陣是為了減少參數(shù)調(diào)整維度實(shí)際工程中如果跟蹤效果出現(xiàn)明顯的振蕩可以進(jìn)一步在位置和速度之間增加相關(guān)性但多數(shù)場(chǎng)景下對(duì)角矩陣已經(jīng)足夠。這個(gè)參數(shù)是整個(gè)濾波器調(diào)參最核心的旋鈕很多跟蹤器調(diào)不好問(wèn)題都出在Q的量級(jí)和視頻幀率不匹配。3.2 預(yù)測(cè)與更新手寫卡爾曼濾波核心循環(huán)卡爾曼濾波的核心循環(huán)就兩步時(shí)間更新預(yù)測(cè)和狀態(tài)更新校正。時(shí)間更新里用F和上一幀的協(xié)方差P計(jì)算出當(dāng)前幀的先驗(yàn)協(xié)方差同時(shí)用F乘以狀態(tài)向量得到先驗(yàn)位置。狀態(tài)更新里先計(jì)算卡爾曼增益K這個(gè)增益表示“預(yù)測(cè)和觀測(cè)各信多少”然后根據(jù)觀測(cè)值z(mì)更新后驗(yàn)狀態(tài)和協(xié)方差。對(duì)一個(gè)單目標(biāo)跟蹤器來(lái)說(shuō)這兩個(gè)步驟只需要十幾行代碼class KalmanBoxTracker: def __init__(self, bbox, dt1.0): self.F make_F(dt) self.Q make_Q(dt) self.H np.array([ [1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0] ], dtypenp.float64) self.R np.eye(4) * 4.0 x, y, w, h bbox vx, vy 0.0, 0.0 self.x np.array([x, y, w, h, vx, vy], dtypenp.float64) self.P np.eye(6) * 10.0 def predict(self): self.x self.F.dot(self.x) self.P self.F.dot(self.P).dot(self.F.T) self.Q return self.x[:4] def update(self, z, confidence1.0): if confidence 0.3: return self.x[:4] z np.array(z, dtypenp.float64) y z - self.H.dot(self.x) S self.H.dot(self.P).dot(self.H.T) self.R K self.P.dot(self.H.T).dot(np.linalg.inv(S)) self.x self.x K.dot(y) self.P (np.eye(6) - K.dot(self.H)).dot(self.P) return self.x[:4]這段代碼的邏輯與工程要點(diǎn)如下。predict()里先預(yù)測(cè)狀態(tài)和協(xié)方差返回的預(yù)測(cè)框用于顯示和門控判斷。update()根據(jù)置信度決定是否執(zhí)行觀測(cè)更新這是一個(gè)工程化的遮擋處理策略而不是教科書里的標(biāo)準(zhǔn)流程。confidence可以來(lái)自檢測(cè)器的得分也可以來(lái)自目標(biāo)外觀匹配的相似度當(dāng)它低于0.3時(shí)只走預(yù)測(cè)不修正狀態(tài)。這里有一個(gè)參數(shù)需要說(shuō)明self.P np.eye(6) * 10.0是初值協(xié)方差它表示第一幀給狀態(tài)的信任度。P設(shè)得大濾波器會(huì)更快地跟隨初始觀測(cè)設(shè)得小初始幾幀的跟蹤會(huì)比較保守。首幀的x、y、w、h直接來(lái)自檢測(cè)框vx、vy初始化為0速度會(huì)在后續(xù)幀中通過(guò)觀測(cè)逐步估計(jì)出來(lái)。對(duì)于第一幀之后馬上出現(xiàn)遮擋的場(chǎng)景vx、vy為0會(huì)導(dǎo)致目標(biāo)默認(rèn)靜止這時(shí)更好的辦法是用前幾幀的檢測(cè)框差分初始化速度減少冷啟動(dòng)誤差。3.3 用檢測(cè)器輸出作為觀測(cè)源最小閉環(huán)運(yùn)行要讓跟蹤器真正跑起來(lái)需要把檢測(cè)器和卡爾曼濾波串成閉合回路。整個(gè)流程是第一幀從檢測(cè)器拿到初始目標(biāo)框后續(xù)每一幀先調(diào)用卡爾曼預(yù)測(cè)獲得預(yù)測(cè)框然后把當(dāng)前幀檢測(cè)器輸出的所有候選框與預(yù)測(cè)框做IoU比較選取IoU最大的候選框作為觀測(cè)值最后調(diào)用update完成狀態(tài)修正。在遮擋和重疊場(chǎng)景里IoU門控本身就在充當(dāng)觀測(cè)質(zhì)量的過(guò)濾器。def track_one_frame(tracker, detections, confidence_scores): pred_box tracker.predict() best_iou -1.0 best_det None best_conf 0.0 for det, conf in zip(detections, confidence_scores): iou compute_iou(pred_box, det) if iou best_iou: best_iou iou best_det det best_conf conf if best_iou 0.3 and best_conf 0.3: tracker.update(best_det, best_conf) else: tracker.update(pred_box, 0.0) return tracker.x這個(gè)流程里有一個(gè)容易忽略的細(xì)節(jié)沒(méi)有有效檢測(cè)框時(shí)代碼仍然會(huì)調(diào)用tracker.update(pred_box, 0.0)也就是用一個(gè)“預(yù)測(cè)值當(dāng)觀測(cè)值”的方式做更新。這樣做的好處是狀態(tài)向量不變只有協(xié)方差繼續(xù)按Q增長(zhǎng)為后續(xù)重檢測(cè)保留合理的搜索范圍。很多人會(huì)在沒(méi)有觀測(cè)時(shí)干脆不調(diào)用update這樣問(wèn)題也不大但要注意協(xié)方差的累積方式是一致的。只要每次都執(zhí)行預(yù)測(cè)協(xié)方差就會(huì)持續(xù)增長(zhǎng)區(qū)別只在于是否注入觀測(cè)。IoU門控的閾值0.3并非通用值。目標(biāo)小、移動(dòng)快的時(shí)候相鄰幀IoU天然偏低閾值設(shè)0.5會(huì)漏掉大量有效觀測(cè)目標(biāo)大、運(yùn)動(dòng)平緩時(shí)閾值0.3又可能把重疊的其他目標(biāo)框誤當(dāng)成觀測(cè)。我一般會(huì)把閾值和視頻幀率聯(lián)動(dòng)考慮30幀以上的視頻可以稍微調(diào)高閾值15幀以下的視頻閾值建議降到0.2左右。4. 遮擋與重疊場(chǎng)景的實(shí)戰(zhàn)策略門控、置信度加權(quán)與軌跡外推跑通最小實(shí)現(xiàn)之后真正的挑戰(zhàn)在于應(yīng)對(duì)復(fù)雜的遮擋和重疊模式。相同的一套卡爾曼濾波算法在不同場(chǎng)景下的處理策略差異非常大這里給出四種我在實(shí)際項(xiàng)目中驗(yàn)證過(guò)的策略以及它們各自適用的場(chǎng)景。4.1 遮擋時(shí)長(zhǎng)分級(jí)短遮擋靠預(yù)測(cè)續(xù)命長(zhǎng)遮擋要?jiǎng)油庥^模型遮擋時(shí)長(zhǎng)是決定跟蹤器存活與否的第一因素。短遮擋通常指3幀以內(nèi)這時(shí)卡爾曼濾波的勻速模型外推誤差很小直接用預(yù)測(cè)框替代檢測(cè)框即可不需要額外處理。中等遮擋指3到10幀這時(shí)目標(biāo)的機(jī)動(dòng)可能導(dǎo)致預(yù)測(cè)位置偏離真實(shí)位置需要適當(dāng)增大Q的縮放因子讓協(xié)方差快速膨脹以便重檢測(cè)時(shí)能覆蓋更大的搜索范圍。長(zhǎng)遮擋指10幀以上單純靠卡爾曼濾波外推已經(jīng)不穩(wěn)定常見(jiàn)的做法是保留目標(biāo)最后已知位置和速度在預(yù)測(cè)框附近啟動(dòng)局部搜索用外觀模型或者檢測(cè)器重新檢測(cè)。這里有個(gè)容易踩的坑有人認(rèn)為遮擋期間完全不更新P等目標(biāo)重新出現(xiàn)時(shí)再一次性修正。實(shí)際上如果P在長(zhǎng)遮擋期間增長(zhǎng)得太慢重檢測(cè)的觀測(cè)會(huì)被“過(guò)度信任”導(dǎo)致軌跡突然跳變?nèi)绻鸓增長(zhǎng)得太快門控范圍太大又可能抓到旁邊的其他目標(biāo)。比較穩(wěn)妥的做法是給P的增長(zhǎng)設(shè)定一個(gè)上限比如位置分量的標(biāo)準(zhǔn)差不超過(guò)目標(biāo)尺寸的1.5倍超過(guò)后保持這個(gè)上限繼續(xù)外推。4.2 重疊場(chǎng)景的觀測(cè)選擇最大置信度還是最大IoU兩個(gè)目標(biāo)重疊時(shí)檢測(cè)器往往只輸出一個(gè)合并框或兩個(gè)互相干擾的框。這時(shí)最簡(jiǎn)單的策略是選IoU最高的框作為卡爾曼濾波的觀測(cè)值。但重疊的目標(biāo)通常外觀相似、位置接近IoU最高的框不一定是主目標(biāo)的框。另一種策略是選擇置信度最高的框因?yàn)闄z測(cè)器通常對(duì)特征更完整的目標(biāo)輸出更高得分。這兩種策略各有適用場(chǎng)景我的經(jīng)驗(yàn)是如果兩個(gè)目標(biāo)運(yùn)動(dòng)方向接近選最大IoU如果運(yùn)動(dòng)方向相反或夾角較大選最大置信度。進(jìn)一步的做法是引入置信度對(duì)觀測(cè)噪聲R的調(diào)制。置信度越高R越小濾波器越信任這個(gè)觀測(cè)置信度越低R越大濾波器更依賴預(yù)測(cè)。這相當(dāng)于在卡爾曼濾波的標(biāo)準(zhǔn)框架里加入了一個(gè)軟門控比硬性的IoU閾值更平滑。具體實(shí)現(xiàn)上把R乘以一個(gè)關(guān)于置信度的單調(diào)遞減函數(shù)即可例如R_eff R / (0.5 confidence)這樣低置信度觀測(cè)的R會(huì)變大高置信度觀測(cè)的R會(huì)變小。4.3 軌跡外推時(shí)的速度衰減策略目標(biāo)被長(zhǎng)遮擋時(shí)勻速假設(shè)會(huì)越來(lái)越不可靠。更合理的做法是讓速度在外推過(guò)程中逐漸衰減到0這相當(dāng)于假設(shè)目標(biāo)最終會(huì)停下來(lái)而不是一直保持遮擋前的速度。實(shí)現(xiàn)方式是在predict步驟中增加一個(gè)衰減系數(shù)lambda每次預(yù)測(cè)時(shí)vx vx * lambdalambda取0.9到0.95之間。這個(gè)衰減在數(shù)學(xué)上相當(dāng)于一個(gè)帶阻尼的運(yùn)動(dòng)模型它可以顯著減少長(zhǎng)遮擋后的位置漂移。不過(guò)要注意速度衰減并不適用于所有目標(biāo)。車輛在遮擋期間幾乎不會(huì)突然停下行人則經(jīng)常改變運(yùn)動(dòng)狀態(tài)。我的做法是對(duì)目標(biāo)類別做區(qū)分車輛類目標(biāo)lambda取0.98行人取0.9這樣既能保留機(jī)動(dòng)性又不會(huì)讓預(yù)測(cè)框跑得太遠(yuǎn)。如果使用的檢測(cè)器同時(shí)輸出類別信息這個(gè)區(qū)分幾乎是零成本的。4.4 重新出現(xiàn)的檢測(cè)框歸屬判斷用馬氏距離取代IoU當(dāng)遮擋目標(biāo)重新出現(xiàn)在畫面中附近的檢測(cè)框可能是目標(biāo)本身也可能是另一個(gè)無(wú)關(guān)目標(biāo)。IoU在此時(shí)不是最好的判據(jù)因?yàn)轭A(yù)測(cè)框和真目標(biāo)可能只有部分重疊。馬氏距離可以考慮協(xié)方差的不確定性它計(jì)算觀測(cè)與預(yù)測(cè)之間的標(biāo)準(zhǔn)化距離距離小說(shuō)明觀測(cè)與預(yù)測(cè)在統(tǒng)計(jì)意義上一致。def mahalanobis_gate(trk, z_bbox): H trk.H P trk.P x_pred trk.x S H.dot(P).dot(H.T) trk.R y np.array(z_bbox) - H.dot(x_pred) dist y.dot(np.linalg.inv(S)).dot(y) return dist, S這里的dist就是馬氏距離的平方通常用卡方分布的95%分位作為門限4維觀測(cè)對(duì)應(yīng)約9.49。如果dist小于這個(gè)門限認(rèn)定觀測(cè)屬于主目標(biāo)否則視為干擾只保留預(yù)測(cè)狀態(tài)。這個(gè)門控在重疊目標(biāo)分離的瞬間特別有用因?yàn)楫?dāng)兩個(gè)目標(biāo)分開(kāi)時(shí)主目標(biāo)的檢測(cè)框可能與預(yù)測(cè)框有一定偏移但馬氏距離仍在門限內(nèi)而其他目標(biāo)的檢測(cè)框則會(huì)被準(zhǔn)確排除。5. 避坑指南遮擋跟蹤器最容易翻車的5個(gè)細(xì)節(jié)卡爾曼濾波的公式本身很簡(jiǎn)單真正讓跟蹤器翻車的地方全在參數(shù)和實(shí)現(xiàn)細(xì)節(jié)上。這一章把我做跟蹤器以來(lái)的踩坑記錄按“現(xiàn)象-原因-解決”整理出來(lái)每一條都來(lái)自實(shí)際調(diào)試上下文。5.1 協(xié)方差P初始化成0導(dǎo)致第一幀之后濾波器完全不更新現(xiàn)象跟蹤器在第一幀之后位置幾乎不動(dòng)即使目標(biāo)明顯移動(dòng)預(yù)測(cè)框也追不上。原因P如果初始化為全零矩陣計(jì)算出的卡爾曼增益K也是零觀測(cè)更新完全不生效。解決P初始化為單位矩陣乘以一個(gè)較大值例如10或100表示初始狀態(tài)不確定。不要直接用全零矩陣也不要直接把檢測(cè)框當(dāng)絕對(duì)真值。5.2 Q參數(shù)設(shè)得太小導(dǎo)致遮擋后目標(biāo)位置永遠(yuǎn)拉不回來(lái)現(xiàn)象目標(biāo)遮擋2秒鐘后重新出現(xiàn)跟蹤框比目標(biāo)慢了一大截并且后續(xù)十幾幀都在緩慢追趕。原因Q太小使得協(xié)方差預(yù)測(cè)增長(zhǎng)緩慢濾波器依然認(rèn)為上一幀的狀態(tài)很可靠拒絕接受新觀測(cè)。解決加大Q中速度分量的variance尤其在低幀率視頻中因?yàn)閹g隔越大目標(biāo)的機(jī)動(dòng)可能越劇烈。經(jīng)驗(yàn)上可以把Q的速度項(xiàng)設(shè)為位置項(xiàng)的100倍量級(jí)。5.3 遮擋期間不做預(yù)測(cè)只等待檢測(cè)框出現(xiàn)現(xiàn)象目標(biāo)被遮擋的幾幀里跟蹤框停在原地一旦目標(biāo)在遠(yuǎn)處重新出現(xiàn)跟蹤框與目標(biāo)距離過(guò)大無(wú)法恢復(fù)。原因遮擋期間完全沒(méi)有調(diào)用卡爾曼預(yù)測(cè)導(dǎo)致?tīng)顟B(tài)和協(xié)方差都停留在最后一幀。解決即使沒(méi)有任何觀測(cè)也要持續(xù)調(diào)用predict()讓狀態(tài)外推、協(xié)方差增長(zhǎng)。這一點(diǎn)在工程實(shí)現(xiàn)里往往被忽略教科書里的卡爾曼循環(huán)雖然寫的是預(yù)測(cè)-更新交替但在視覺(jué)跟蹤里預(yù)測(cè)必須每幀都執(zhí)行。5.4 重疊時(shí)用原始檢測(cè)框更新導(dǎo)致跟蹤框在兩個(gè)目標(biāo)之間反復(fù)跳變現(xiàn)象兩個(gè)行人并肩而行時(shí)跟蹤框一會(huì)兒在左邊目標(biāo)上一會(huì)兒在右邊目標(biāo)上。原因檢測(cè)器輸出的框在兩個(gè)目標(biāo)之間搖擺卡爾曼濾波沒(méi)有區(qū)分觀測(cè)來(lái)源把每個(gè)框都當(dāng)成有效觀測(cè)。解決把IoU門限調(diào)高同時(shí)結(jié)合速度和尺寸的一致性約束只接受尺寸變化在20%以內(nèi)、位置偏移在合理范圍內(nèi)的檢測(cè)框。不要只依賴IoU重疊目標(biāo)的IoU可能都很高。5.5 R參數(shù)固定不變導(dǎo)致光照突變和多目標(biāo)重疊時(shí)跟蹤精度雙雙下降現(xiàn)象目標(biāo)進(jìn)入陰影區(qū)域時(shí)檢測(cè)框抖動(dòng)明顯跟蹤框也跟隨著高頻抖動(dòng)目標(biāo)重疊時(shí)跟蹤框被吸入另一個(gè)目標(biāo)。原因固定R意味著濾波器對(duì)所有觀測(cè)的信任度恒定但不同場(chǎng)景下檢測(cè)器的定位噪聲差異很大。解決R與檢測(cè)置信度聯(lián)動(dòng)或者與目標(biāo)區(qū)域內(nèi)的對(duì)比度關(guān)聯(lián)。置信度低時(shí)放大R置信度高時(shí)縮小R。這里有個(gè)量化參考置信度從0.9降到0.5時(shí)R一般放大2到3倍。6. 把跟蹤器做扎實(shí)遮擋恢復(fù)驗(yàn)證與跨參數(shù)評(píng)估技巧最后這章講怎么驗(yàn)證跟蹤器真的做好了。只跑一段視頻看不出效果正確做法是用模擬軌跡和真實(shí)視頻兩種方式做系統(tǒng)評(píng)估。模擬軌跡的好處是擁有真值可以量化誤差真實(shí)視頻的挑戰(zhàn)是標(biāo)注成本高但能檢驗(yàn)實(shí)際場(chǎng)景的復(fù)雜性。我習(xí)慣先做前一種再做后一種。6.1 用模擬軌跡驗(yàn)證遮擋恢復(fù)能力在合成數(shù)據(jù)上你可以生成一條勻速或勻加速運(yùn)動(dòng)的軌跡并在中間人為挖掉一段時(shí)間作為遮擋。然后運(yùn)行跟蹤器比較遮擋前后的預(yù)測(cè)軌跡與真值之間的誤差。這樣能驗(yàn)證三個(gè)指標(biāo)遮擋期間的位置漂移速度、遮擋結(jié)束后的重捕獲率、重捕獲后的收斂幀數(shù)。def simulate_occlusion_test(tracker, gt_traj, occl_frames): errors [] for t, gt in enumerate(gt_traj): if t in occl_frames: tracker.update(pred_box, 0.0) err np.linalg.norm(tracker.x[:2] - gt[:2]) else: tracker.update(gt, 1.0) err np.linalg.norm(tracker.x[:2] - gt[:2]) errors.append(err) return errors這段代碼直接在每一幀用真值作為觀測(cè)進(jìn)行更新但在遮擋幀強(qiáng)制不更新。它用來(lái)檢驗(yàn)濾波器的狀態(tài)外推能力和P的膨脹速度是否匹配。理想的曲線是遮擋期間誤差線性增長(zhǎng)遮擋結(jié)束后誤差在3到5幀內(nèi)回到遮擋前水平。如果誤差增長(zhǎng)是二次的說(shuō)明Q中速度項(xiàng)權(quán)重大大如果恢復(fù)需要超過(guò)10幀說(shuō)明R相對(duì)P而言太大濾波器對(duì)新觀測(cè)反應(yīng)過(guò)慢。這種量化分析比肉眼觀察跟蹤框更可靠也是卡爾曼濾波算法調(diào)參時(shí)最有效的實(shí)操手段。6.2 橫向?qū)Ρ热N門控策略的邊界做完模擬驗(yàn)證后真實(shí)視頻上還要做橫向?qū)Ρ取N彝ǔ?huì)同時(shí)跑三種配置純IoU門控、IoU加置信度加權(quán)、馬氏距離門控。在遮擋頻繁的視頻上純IoU門控的跟蹤成功率偏低原因是遮擋期間干擾物與預(yù)測(cè)框的IoU可能高于真實(shí)目標(biāo)置信度加權(quán)能改善一部分但檢測(cè)器本身置信度不可靠時(shí)會(huì)引入新的噪聲馬氏距離門控在目標(biāo)分離瞬間表現(xiàn)最好因?yàn)樗瑫r(shí)考慮了狀態(tài)不確定性但計(jì)算量稍大。單一指標(biāo)不夠全面我建議同時(shí)統(tǒng)計(jì)三個(gè)數(shù)字跟蹤成功率、中心位置誤差、被替換到其他目標(biāo)上的次數(shù)。第一個(gè)數(shù)字衡量整體穩(wěn)定性第二個(gè)數(shù)字衡量跟蹤精度第三個(gè)數(shù)字專門衡量重疊場(chǎng)景下的ID混淆程度。后一個(gè)指標(biāo)能直接反映門控策略是否有效防止了目標(biāo)之間地串?dāng)_。6.3 一組可抄的參數(shù)模板與調(diào)參順序結(jié)合前面的分析給出一個(gè)經(jīng)過(guò)多組實(shí)驗(yàn)驗(yàn)證的起始參數(shù)模板。需要說(shuō)明的是這組參數(shù)是針對(duì)30fps視頻、中等大小目標(biāo)、普通移動(dòng)速度設(shè)計(jì)的具體應(yīng)用時(shí)應(yīng)該以它為起點(diǎn)而不是終點(diǎn)。Q的位置噪聲std_pos取0.01速度噪聲std_acc取0.5R對(duì)角線取4IoU門限取0.3置信度門限取0.3馬氏距離門限取9.49。調(diào)參順序上先調(diào)R再調(diào)Q因?yàn)镽直接決定跟蹤器對(duì)觀測(cè)的信任程度調(diào)好R之后再根據(jù)遮擋恢復(fù)速度調(diào)整Q。如果跟蹤器表現(xiàn)出振蕩優(yōu)先減小R如果表現(xiàn)出遲滯優(yōu)先增大Q。大部分跟蹤效果不佳的問(wèn)題都能歸因到R和Q的比例偏離合理區(qū)間這個(gè)根因上。這個(gè)方案最后值得投入的地方在于卡爾曼濾波帶來(lái)的不是算力成本而是工程細(xì)節(jié)的耐心。遮擋與重疊環(huán)境下的單目標(biāo)跟蹤器真正比拼的是誰(shuí)的門控策略更貼合目標(biāo)運(yùn)動(dòng)規(guī)律誰(shuí)的參數(shù)初始化更符合視頻特性。我在每次部署新場(chǎng)景時(shí)都會(huì)保留一份遮擋幀索引和對(duì)應(yīng)的誤差曲線下次調(diào)參直接對(duì)照曲線說(shuō)話而不是靠感覺(jué)。希望這些細(xì)節(jié)能幫你在做類似單目標(biāo)跟蹤器方案時(shí)少走一段彎路。本文還有配套的精品資源點(diǎn)擊獲取