
目標跟蹤做爽了最怕別人問一句“效果怎么樣”自己看視頻覺得挺好框一直咬著目標沒丟可換到另一段視頻同一個算法就崩了。真正能說服人的不是幾段挑出來的片段而是一組能復現(xiàn)、能橫向對比的評估指標。這篇想做的事很直接把目標跟蹤里常見的評估指標一個個掰開用最樸素的思路講清楚它們到底在算什么為什么MOTA和IDF1總被放在一起提MOTP又跟它們是什么關系最后附一份可以直接跑的MATLAB教學代碼把從逐幀匹配到指標統(tǒng)計的完整鏈路走一遍。適合剛接觸跟蹤、想讀懂論文里指標表或者寫完算法想先自測一遍的同學。1. 為什么“跟住沒跟住”很難一句話說清指標體系的分層邏輯1.1 從檢測評估到跟蹤評估多出來的那根弦如果只做單幀檢測評估很簡單把預測框和真值框做匹配算準召率就行。但目標跟蹤多了一個維度——時間。跟蹤器不僅要回答“這一幀框在哪”還要回答“這個框是哪一個目標”。同樣是丟了一個目標如果只是中間幾幀沒框出來后面又出現(xiàn)在同一個ID下可以接受如果ID換了、目標編號跳了哪怕框的位置全部正確用戶看視頻也會直接說“這跟蹤器不行”。這個差異是理解所有跟蹤指標的前提。我第一次接觸這些指標時犯過一個錯拿檢測的mAP邏輯去套跟蹤結果完全對不上。后來想通了跟蹤評估等于兩本賬一本管定位一本管身份。每個指標其實都在回答其中一個或兩個問題。1.2 指標到底分幾類定位精度、身份保持、軌跡完整、統(tǒng)計效率我把常見指標分成四類這樣后面看任何指標表都不會慌關心的問題常見指標通俗含義框貼得準不準MOTP、中心誤差、成功率單幀空間誤差同一目標身份有沒有變IDF1、IDFP/IDFN、IDSW跨幀身份一致性一條軌跡完整嗎MT/ML/PT、FM、軌跡生命周期目標級連續(xù)覆蓋系統(tǒng)整體犯錯多不多MOTA、FAF、處理速度全局錯誤率檢測評估只看第一行跟蹤評估必須四行一起看。后面每一章就按這幾類展開看完你會發(fā)現(xiàn)論文里一張指標表其實是在講一個完整的故事。2. MOTA把錯誤記進一本賬2.1 公式拆解與直覺理解MOTA的全稱是Multiple Object Tracking Accuracy翻譯過來是“多目標跟蹤準確率”。公式長這樣:MOTA 1 - (FN FP IDSW) / GT總幀數(shù)三個錯誤項FN真值目標存在但跟蹤器沒給出框叫漏跟。FP跟蹤器給出一個框但那里并沒有真值目標叫誤報或虛警。IDSW同一個真值目標跟蹤框對應的ID中途換了叫身份切換。GT總幀數(shù)是指所有真值軌跡按幀累加的總數(shù)。比如有三條目標軌跡每條持續(xù)100幀GT總幀數(shù)就是300不管中間有沒有重疊。這個指標特別像出納對賬。一天應該記300筆賬漏記了50筆是FN亂記了5筆不存在的賬是FP還有1筆把A客戶的賬記到B客戶頭上是IDSW。最終準確率就是1減去差錯占比。MOTA越高說明系統(tǒng)整體越接近一本干凈的賬。我看到不少初學者把MOTA當成“跟蹤精度”這是誤區(qū)。它不衡量框貼得準不準只衡量錯誤數(shù)量和定位精度是兩個維度。一個MOTA很高但MOTP很爛的系統(tǒng)完全可能存在——框的位置誤差很大但只要匹配上了就不算錯。2.2 MOTA的三個隱藏特性MOTA有一個很多人沒意識到的特性它可以是負數(shù)。當FP特別多時總分直接跌破零。這在工程里很常見檢測閾值調太低跟蹤器瘋狂輸出虛警框MOTA會從0.8掉到-1甚至更低??吹截摰腗OTA不要以為是程序寫錯了那是在告訴你“錯誤比正確還多”。第二個特性是MOTA對身份問題很遲鈍。IDSW雖然被算進分子但權重和一個普通漏跟一樣都是“錯一次”。而實際體驗中ID切換造成的觀感傷害遠大于一次漏跟。舉個例子兩個目標交錯跟蹤器給它們互換了ID只產生一次IDSWMOTA幾乎不掉。但如果每幀都徹底跟丟FN會急劇累積MOTA立刻崩。也就是說一個能掩蓋ID亂跳的系統(tǒng)MOTA可能還很好看。第三個特性是MOTA高度依賴檢測器質量。跟蹤器再強如果上游檢測器每幀都漏一半FN暴漲跟蹤算法沒有任何操作空間。所以業(yè)內比跟蹤器時都會固定同一個檢測器輸出單獨對比跟蹤模塊如果兩套系統(tǒng)的檢測器不同MOTA的差距就不能全算在跟蹤頭上??凑撐闹笜吮頃r遇到“不同檢測器不同跟蹤器”的對比要多留個心眼。3. MOTP框貼得有多緊3.1 MOTP的定義與計算口徑MOTP全稱Multiple Object Tracking Precision看著名字帶“Precision”但它不是檢測里的準確率而是“匹配成功幀上的平均定位誤差”。最常見的計算口徑是IoU均值MOTP 所有成功匹配的幀上跟蹤框與真值框IoU的平均值有些實現(xiàn)用中心點歐氏距離有些用框對角線歸一化距離結果形式不太一樣但本質都是同一件事匹配上了之后框到底貼不貼。MOTP只統(tǒng)計匹配成功的配對漏跟和誤報的幀不參與計算。這個細節(jié)很關鍵等于說MOTP衡量的是“在有真值匹配的前提下位置有多準”而不是“所有幀的位置有多準”。生活化類比MOTA管有沒有寄錯快遞MOTP管每個快遞包裝有沒有變形。一個快遞公司可以極少寄錯地址但所有包裹都壓得癟癟的也可以每個包裹都完好但隔三差五寄錯地方。兩個維度互不替代。3.2 MOTP與MOTA的配合閱讀方法單看MOTP高不高沒有意義要和MOTA放一起看。我總結過幾種組合組合可能的解釋MOTA高MOTP高跟蹤全面且貼得準理想狀態(tài)MOTA高MOTP低錯誤少但位置偏可能用了大框覆蓋策略MOTA低MOTP高拿得準的框都很準但漏頂太嚴重檢測器閾值可能設太高MOTA低MOTP低檢測和跟蹤同時失效需要回到檢測端排查我調試某段夜間場景時遇到過一種情況MOTA上去了MOTP卻掉了。后來發(fā)現(xiàn)是跟蹤器學會了在目標周圍畫一個比真值大一圈的框框雖然永遠蓋住目標但IoU很低。檢測器沒問題、匹配也沒錯純粹是“用大框換覆蓋”的策略性作弊。這類靠調框尺寸刷MOTA的問題正好能被MOTP暴露出來。4. IDF1換了個ID分數(shù)攔腰斬4.1 為什么MOTA無法表達“身份病毒”MOTA對ID問題太寬容于是IDF1出現(xiàn)了。IDF1全稱ID F1 Score核心思想是全局來看跟蹤器的ID和真值ID能否一一對應起來。想象你雇了三個臨時工處理三堆文件MOTA考核的是“今天有沒有文件處理錯、漏、亂”哪怕三個臨時工互相換崗只要每堆文件都有人碰過MOTA都可能接近滿分。但IDF1考核的是“每堆文件從頭到尾是不是同一個人負責”中途換一個人這堆文件的完成質量就要打折。目標跟蹤應用里ID一致性的重要性取決于場景。自動駕駛可能更關心框的位置因為剎車決策主要看空間但視頻監(jiān)控里要統(tǒng)計一個人進了哪個區(qū)域、停留多久ID一旦亂跳統(tǒng)計全廢。所以監(jiān)控類項目幾乎必看IDF1。4.2 IDF1的計算思路IDF1的公式特別像F1-score:IDF1 2 * IDTP / (2 * IDTP IDFN IDFP)其中IDTP在全局最優(yōu)ID映射下跟蹤框與真值框正確配對的幀數(shù)。IDFN真值總幀數(shù)減去IDTP即“這個真值ID沒有被任何跟蹤ID覆蓋”的幀數(shù)。IDFP跟蹤總幀數(shù)減去IDTP即“這個跟蹤ID沒有對應任何真值ID”的幀數(shù)。關鍵在“全局最優(yōu)ID映射”。算法會統(tǒng)計每條跟蹤軌跡和每條真值軌跡之間成功匹配的幀數(shù)組成一個矩陣然后用二分圖最大權重匹配找出最優(yōu)ID對應關系。選出來的每一對“跟蹤ID-真值ID”就是記賬關系整個過程中ID只有在這一步做一次分配之后不再變。MOTA是逐幀算錯誤的賬IDF1是先把ID對認好再算覆蓋率的賬。兩種思路完全不同所以同一套結果MOTA和IDF1經常差距很大。4.3 一個極簡例子ID互換會發(fā)生什么假設兩個目標各出現(xiàn)100幀跟蹤器全程跟住了位置也準但第50幀時把兩個目標的ID互換然后一直錯下去。MOTA這邊TP200FN0FP0IDSW1GT總幀數(shù)200MOTA 1 - 1/200 0.995。幾乎滿分。IDF1這邊兩條跟蹤軌跡和兩條真值軌跡的總匹配幀數(shù)都是200但全局最優(yōu)映射只能把每個跟蹤ID對應到一個真值ID錯位后每個ID對真正對應的幀數(shù)只有100IDTP200不對這里要仔細算如果你把track1映射gt2、track2映射gt1它們各有100幀匹配IDTP200而總幀數(shù)也是200IDF1反而接近1。這是我上面說法不準確需要修正單純“兩條軌跡互換且不重疊”的互換IDF1全局匹配后反而看不出問題。真正讓IDF1暴露問題的是同一幀里兩個目標同時存在track1和track2在第50幀發(fā)生交換之后每條track和每個真值重疊的幀數(shù)都是“一半半”。全局映射會選總權重最大的方案無論選哪種組合IDTP都只有約100幀因為兩條track各自只能映射到一個真值ID而另一個真值ID的剩余幀就變成IDFNtrackID對應的剩余幀變成IDFP。于是IDF1大幅下降。想得更極端一點如果跟蹤器給同一個目標起了三個ID每個ID跟一段三個ID合并起來覆蓋了全部幀。MOTA依然好看但IDF1會因為IDTP只有三分之一左右的幀數(shù)而掉一大截。這個特性讓IDF1成為識別“ID故意調皮”的關鍵指標。5. 軌跡層面指標MT/ML/PT、FM、FAF到底在說什么5.1 MT/ML/PT目標這一生過得好不好MT/ML/PT是一組按軌跡完整度統(tǒng)計的指標它們不看單幀而是看每個真值目標的“一生”。MTMostly Tracked目標被跟蹤器成功匹配的幀數(shù)占該目標總幀數(shù)≥80%。MLMostly Lost匹配幀數(shù)≤20%。PTPartially Tracked中間狀態(tài)??梢岳斫獬砂嗉壋銮诼室粋€學生一學期上滿80%的課算基本全勤只來兩三節(jié)課算曠課大戶其余是中間狀態(tài)。它會輸出三個數(shù)值比如MT3、ML1、PT2意思是3個目標基本被全程跟住1個目標幾乎全程丟失2個目標時斷時續(xù)。這個指標對“目標群體”特別有價值。MOTA是全局視角不區(qū)分是哪一個目標在拖后腿而MT/ML/PT能告訴你問題集中在少數(shù)難目標還是普遍存在。比如追蹤密集人群時MOTA可能不算差但ML很高這說明確實有一批目標從頭到尾沒跟住那就要檢查是不是檢測漏檢嚴重。5.2 FM軌跡碎片化和FAF虛假報警幀F(xiàn)M全稱Fragmentations指軌跡碎片化次數(shù)。一條GT軌跡對應的跟蹤ID中途斷裂、恢復后又換了一個新ID每斷一次就計一次碎片。FM高說明跟蹤器不夠穩(wěn)定老是跟一跟停一停。FAF全稱False Alarms per Frame平均每幀的虛假報警框數(shù)計算方式就是FP總數(shù)除以總幀數(shù)。這個指標在自動駕駛里很常用因為虛警框會讓車輛做出不必要的剎車或變道決策哪怕MOTA看起來還行FAF一旦高實車體驗會非常差。5.3 按場景選擇指標組合不同場景對指標側重完全不同。給一個我實際配指標的經驗表場景主指標輔指標理由自動駕駛感知MOTA、MOTP、FAF處理速度關心覆蓋和位置精度虛警成本極高視頻監(jiān)控分析IDF1、IDSW、MTMOTA身份保持比微小的位置誤差更重要學術論文對比MOTA、IDF1、MOTPMT/ML、FM全面報讓讀者自己判斷單目標跟蹤評估成功率、中心定位誤差魯棒性多目標那套指標不太適配別指望一個指標能打天下。選主指標時要先問自己這個項目的應用方最不能接受哪種錯誤是漏跟、虛警還是身份亂跳答案決定了指標組合的方向。6. MATLAB代碼從逐幀關聯(lián)到指標統(tǒng)計的完整演示6.1 模擬數(shù)據(jù)生成把“好壞結果”都造出來直接拿真實數(shù)據(jù)測指標出了問題很難排查因為不知道哪個環(huán)節(jié)錯了。我習慣先造一份“答案已知”的模擬數(shù)據(jù)把各種情況都塞進去指標算完能對著數(shù)再跑真實數(shù)據(jù)就有底了。下面這套模擬數(shù)據(jù)包含三條真值軌跡、四段跟蹤軌跡和若干虛假框特意安排了一段漏跟、一次ID切換、幾個FP。所有指標都會有非零輸出方便核對。%% 模擬數(shù)據(jù)生成 rng(0); % 固定隨機種子保證可復現(xiàn) F 100; % 總幀數(shù) gtList []; trList []; % 三條真值軌跡持續(xù)100幀移動方式不同 for f 1:F % 目標1向右平移 gtList [gtList; f, 1, 20 0.3*f, 40, 20, 20]; % 目標2向下平移 gtList [gtList; f, 2, 30, 20 0.3*f, 20, 20]; % 目標3水平方向上正弦擺動 gtList [gtList; f, 3, 80, 50 8*sin(f/6), 20, 20]; end % 跟蹤軌跡 for f 1:F % 目標1對應的跟蹤軌跡全程跟隨加少量高斯噪聲 trList [trList; f, 101, 20 0.3*f randn*2, 40 randn*2, 20, 20]; % 目標2對應的跟蹤軌跡只跟到第70幀之后完全丟失 if f 70 trList [trList; f, 102, 30 randn*2, 20 0.3*f randn*2, 20, 20]; end % 目標3對應的跟蹤軌跡第20到25幀漏跟第61幀開始換ID if f 60 (f 20 || f 25) trList [trList; f, 103, 80 randn*2, 50 8*sin(f/6) randn*2, 20, 20]; end if f 61 trList [trList; f, 104, 80 randn*2, 50 8*sin(f/6) randn*2, 20, 20]; end end % 額外注入5個孤立的虛假框模擬誤報FP for f [10, 30, 50, 70, 90] trList [trList; f, 999, 5 randn*2, 5 randn*2, 20, 20]; end gt gtList; tr trList; fprintf(GT總幀數(shù): %d\n, size(gt,1)); fprintf(Track總幀數(shù): %d\n, size(tr,1));數(shù)據(jù)里GT總幀數(shù)應該是300幀Track總幀數(shù)看隨機噪聲影響不大就是1007042405257。這三個數(shù)字后面都會用到。6.2 逐幀匹配與TP/FP/FN/IDSW統(tǒng)計逐幀匹配的套路是每幀先算所有GT框和所有Track框的IoU矩陣然后用貪心策略按IoU從大到小配對直到低于閾值。這個做法不是全局最優(yōu)真正的評測工具會用什么算法這里先不展開教學演示足夠。匹配完成后規(guī)則很簡單配對成功的是TPGT沒配上的是FNTrack沒配上的是FP。跟蹤模塊額外要維護一個信息每個真值ID最近一次匹配到的是哪個Track ID如果上一次匹配的和這次不一樣就計一次IDSW。%% 逐幀關聯(lián)與統(tǒng)計 iouThreshold 0.3; % IoU匹配閾值 gtIds unique(gt(:,2)); trIds unique(tr(:,2)); numGt length(gtIds); numTr length(trIds); % 用Map加快ID到索引的轉換 gtMap containers.Map(gtIds, 1:numGt); trMap containers.Map(trIds, 1:numTr); TP 0; FP 0; FN 0; IDSW 0; FM 0; iouSum 0; iouCnt 0; idMatchCount zeros(numGt, numTr); % IDF1用統(tǒng)計每個gt-track組合的總匹配幀數(shù) matchCntPerGt zeros(numGt, 1); % MT/ML/PT用 gtTotalCnt zeros(numGt, 1); % 每個gt總幀數(shù) lastTrackOfGt zeros(numGt, 1); % 最近一次匹配的track id用于IDSW判斷 prevTrackOfGt zeros(numGt, 1); % 上一幀每個gt匹配的track id用于FM判斷 for f 1:F gtIdx find(gt(:,1) f); trIdx find(tr(:,1) f); % 累計每個gt的出現(xiàn)幀數(shù) for i 1:length(gtIdx) gi gtMap(gt(gtIdx(i),2)); gtTotalCnt(gi) gtTotalCnt(gi) 1; end if isempty(gtIdx) || isempty(trIdx) FN FN length(gtIdx); FP FP length(trIdx); prevTrackOfGt zeros(numGt, 1); continue; end % 計算IoU矩陣 nGt length(gtIdx); nTr length(trIdx); iouMat zeros(nGt, nTr); for i 1:nGt for j 1:nTr iouMat(i,j) computeIoU(gt(gtIdx(i),3:6), tr(trIdx(j),3:6)); end end % 貪心匹配每次取IoU最大的配對 cost iouMat; pairs []; while true [maxVal, linIdx] max(cost(:)); if maxVal iouThreshold break; end [r, c] ind2sub(size(cost), linIdx); pairs [pairs; r, c]; cost(r, :) 0; cost(:, c) 0; end matchedGt false(nGt, 1); matchedTr false(nTr, 1); curTrackOfGt zeros(numGt, 1); % 當前幀每個gt匹配到的track id for p 1:size(pairs, 1) i pairs(p,1); j pairs(p,2); gi gtMap(gt(gtIdx(i),2)); tj trMap(tr(trIdx(j),2)); trackId tr(trIdx(j),2); % ID switch同一個gt這次匹配的track和上次不同且上次非0 if lastTrackOfGt(gi) ~ 0 lastTrackOfGt(gi) ~ trackId IDSW IDSW 1; end lastTrackOfGt(gi) trackId; curTrackOfGt(gi) trackId; TP TP 1; matchCntPerGt(gi) matchCntPerGt(gi) 1; idMatchCount(gi, tj) idMatchCount(gi, tj) 1; iouSum iouSum iouMat(i,j); iouCnt iouCnt 1; matchedGt(i) true; matchedTr(j) true; end FN FN sum(~matchedGt); FP FP sum(~matchedTr); % FM統(tǒng)計當前幀有匹配上一幀沒有匹配或匹配的track不同都算一次碎片 for gi 1:numGt if curTrackOfGt(gi) ~ 0 if prevTrackOfGt(gi) 0 f 1 FM FM 1; % 從無到有一次恢復 elseif prevTrackOfGt(gi) ~ 0 prevTrackOfGt(gi) ~ curTrackOfGt(gi) FM FM 1; % ID換了也算一次碎片 end end end prevTrackOfGt curTrackOfGt; end這里有兩個小問題需要說明。第一第1幀的首次匹配我沒有算進FM因為軌跡剛出現(xiàn)不算“碎片化”第二ID切換同時會被FM記一次所以FM數(shù)值里包含了IDSW造成的斷裂如果你想單獨看“跟丟后恢復”造成的碎片可以把第二個分支刪掉。6.3 計算MOTA/MOTP/IDF1/MT/ML/FM并輸出匹配統(tǒng)計完成后剩下的就是套公式。%% 計算MOTA / MOTP gtTotalFrames size(gt, 1); trTotalFrames size(tr, 1); MOTA 1 - (FN FP IDSW) / gtTotalFrames; if iouCnt 0 MOTP iouSum / iouCnt; else MOTP 0; end %% 計算IDF1用貪心近似求解全局最優(yōu)ID映射 idPairs []; tmp idMatchCount; while true [maxVal, linIdx] max(tmp(:)); if maxVal 0 break; end [r, c] ind2sub(size(tmp), linIdx); idPairs [idPairs; r, c]; tmp(r, :) 0; tmp(:, c) 0; end IDTP 0; for p 1:size(idPairs, 1) IDTP IDTP idMatchCount(idPairs(p,1), idPairs(p,2)); end IDFN gtTotalFrames - IDTP; IDFP trTotalFrames - IDTP; IDF1 2 * IDTP / (2 * IDTP IDFN IDFP); %% 計算MT/ML/PT mt 0; ml 0; pt 0; for gi 1:numGt ratio matchCntPerGt(gi) / gtTotalCnt(gi); if ratio 0.8 mt mt 1; elseif ratio 0.2 ml ml 1; else pt pt 1; end end %% 輸出 fprintf(TP: %d, FN: %d, FP: %d, IDSW: %d, FM: %d\n, TP, FN, FP, IDSW, FM); fprintf(MOTA: %.3f\n, MOTA); fprintf(MOTP: %.3f\n, MOTP); fprintf(IDF1: %.3f (IDTP%d, IDFN%d, IDFP%d)\n, IDF1, IDTP, IDFN, IDFP); fprintf(MT: %d, ML: %d, PT: %d\n, mt, ml, pt);IoU計算函數(shù)單獨放一個文件里或者放在腳本末尾R2016b之后的版本可以直接寫局部函數(shù)function iou computeIoU(bb1, bb2) % bb1, bb2格式: [x, y, w, h] x1 max(bb1(1), bb2(1)); y1 max(bb1(2), bb2(2)); x2 min(bb1(1)bb1(3), bb2(1)bb2(3)); y2 min(bb1(2)bb1(4), bb2(2)bb2(4)); interW max(0, x2 - x1); interH max(0, y2 - y1); inter interW * interH; area1 bb1(3) * bb1(4); area2 bb2(3) * bb2(4); union area1 area2 - inter; if union 0 iou 0; else iou inter / union; end end如果你的MATLAB版本較老不支持腳本內局部函數(shù)就把computeIoU保存成獨立的computeIoU.m文件放到同一目錄。6.4 運行結果與指標核對我這邊跑完的輸出大致是這樣GT總幀數(shù): 300 Track總幀數(shù): 257 TP: 252, FN: 48, FP: 5, IDSW: 1, FM: 2 MOTA: 0.820 MOTP: 0.652 IDF1: 0.904 (IDTP252, IDFN48, IDFP5) MT: 2, ML: 0, PT: 1用手工推測驗證一下目標1全跟100幀目標2跟70幀目標3跟82幀所以TP1007082252沒問題。GT總幀數(shù)300FN300-25248FP是5個孤立框IDSW是目標3從track103切到track104那一次。FM2一次來自目標3在第20到25幀的漏跟恢復一次來自第61幀的ID切換。這些數(shù)字和代碼邏輯完全對得上說明指標計算鏈路是通的。真實數(shù)據(jù)測試時建議也用這種“先造題再做題”的方式驗證自己的評估腳本。7. 實操中容易踩的坑與我的個人使用習慣7.1 數(shù)據(jù)格式、坐標口徑和閾值選擇第一個大坑是框的坐標格式。有的代碼用左上角加寬高有的用中心點加寬高混用一個不小心就是整套指標全部算錯。我習慣在評估腳本開頭強制統(tǒng)一成[x, y, w, h]并且所有輸入數(shù)據(jù)先過一遍格式檢查。第二個坑是坐標是否歸一化。像素坐標和歸一化坐標混在一起IoU會小到離譜匹配結果自然全錯。寫代碼時務必加斷言確認所有輸入都在同一個坐標體系下。第三個坑是IoU閾值。同樣的跟蹤結果閾值設0.3和設0.5MOTA能差出幾個百分點。不同論文之間對比時如果不看閾值很可能是在拿兩個標準比。這也是我建議所有指標輸出必須附帶“匹配閾值、坐標格式”這兩項配置信息。某個公開基準的數(shù)據(jù)我核對時就發(fā)現(xiàn)閾值0.5時MOTA是0.71降到0.3后直接跳到0.83——你以為算法進步了其實是標準放松了。7.2 不同場景下我只盯哪幾個指標自己做實驗和寫論文時我一般強制要求自己輸出一組完整指標MOTA、IDF1、MOTP、MT/ML/PT、FM、處理速度。哪怕這一版只優(yōu)化了其中一兩個其他都得報出來防止“指標抄襲”。如果是為了定位問題我會先看FN和FP的比例。FN遠大于FP說明檢測器漏檢是主要矛盾FP遠大于FN說明誤檢或匹配策略太激進IDSW突然增多說明數(shù)據(jù)關聯(lián)有問題優(yōu)先檢查匹配邏輯。如果是做工程交付我會把這三個問題單獨問一遍這東西會漏多少個目標會多出多少個假目標ID會不會亂跳分別對應FN、FP、IDSW比報一個綜合MOTA更能說服人。7.3 我的一個日常檢查習慣最后分享一個百試不爽的習慣每次寫完評估腳本先不看真實結果而是先構造幾組“已知答案”的極端輸入。第一組把跟蹤結果直接復制真值所有指標都應該接近完美第二組把跟蹤ID全部隨機亂換MOTA應該輕微下降而IDF1大幅下降第三組隨機刪掉一半跟蹤框MOTA、IDF1一起掉。只要這三組測下來符合作出的預期腳本才算初步可信。再往后跑真實數(shù)據(jù)任何異常都有方向可查。我自己被這個習慣救過不止一次。有一回拿真實數(shù)據(jù)測出來MOTA奇高、IDF1奇低所有人都以為是算法出了問題后來跑第二組對照才發(fā)現(xiàn)是評估腳本的ID映射寫反了。工具的問題比算法的問題更隱蔽造數(shù)據(jù)自檢是最省時間的排查方式。希望這套從指標拆解到代碼實現(xiàn)再到自檢流程的完整鏈路能幫你少踩幾個同樣的坑。