實(shí)戰(zhàn):8300張YOLO數(shù)據(jù)集從訓(xùn)練到TensorRT部署)
做智慧交通項(xiàng)目這些年頭盔檢測(cè)是我被問(wèn)得最多的場(chǎng)景之一。原因很簡(jiǎn)單道路監(jiān)控里識(shí)別摩托車(chē)、電動(dòng)車(chē)騎乘人員有沒(méi)有戴頭盔既是交警非現(xiàn)場(chǎng)執(zhí)法的輔助手段也是工地、園區(qū)、校園周邊安全管理的剛需。但真正動(dòng)手做的人都知道第一關(guān)往往不是模型選型而是數(shù)據(jù)集——你手上沒(méi)有一套標(biāo)注規(guī)范、場(chǎng)景齊全、拿來(lái)就能訓(xùn)練的圖后面一切算法都是空中樓閣。這篇博文要聊的就是一套8300張YOLO格式的頭盔檢測(cè)數(shù)據(jù)集在智慧交通場(chǎng)景下的完整使用思路。我按自己實(shí)際做項(xiàng)目的流程來(lái)寫(xiě)先講清楚這套數(shù)據(jù)到底能解決什么問(wèn)題、8300張是什么概念再拆解YOLO的標(biāo)注格式和類(lèi)別設(shè)計(jì)然后是模型選型邏輯、訓(xùn)練實(shí)操、踩坑排查最后落到TensorRT部署和多路監(jiān)控的工程化。無(wú)論你是剛接觸目標(biāo)檢測(cè)的學(xué)生還是已經(jīng)在做智慧交通落地的工程師照著這條線走一遍應(yīng)該能把一個(gè)頭盔檢測(cè)任務(wù)從零跑到上線。1. 盔檢測(cè)數(shù)據(jù)集的真實(shí)定位不只是有沒(méi)有戴帽子這么簡(jiǎn)單1.1 任務(wù)邊界檢測(cè)、分類(lèi)與跟蹤的層次關(guān)系頭盔檢測(cè)表面上是一個(gè)目標(biāo)檢測(cè)任務(wù)但落到實(shí)際業(yè)務(wù)里它其實(shí)是人車(chē)關(guān)系判斷的一環(huán)。監(jiān)控畫(huà)面里有騎手、有車(chē)輛、有行人你要做的不是把畫(huà)面里所有像頭盔的圓形物體框出來(lái)而是先鎖定騎乘人員rider再判斷他頭部區(qū)域有沒(méi)有頭盔。這個(gè)順序很重要——如果先檢測(cè)頭盔再關(guān)聯(lián)人員很容易被路邊安全帽、車(chē)筐里的頭盔、甚至圓形井蓋干擾。所以很多高質(zhì)量的頭盔檢測(cè)數(shù)據(jù)集標(biāo)注類(lèi)別并不是簡(jiǎn)單的一類(lèi)helmet而是包含 rider、helmet、head未戴頭盔的頭部這樣的多類(lèi)別組合。模型同時(shí)學(xué)會(huì)這個(gè)人和這個(gè)人頭上有沒(méi)有東西下游做業(yè)務(wù)判斷時(shí)直接用坐標(biāo)關(guān)聯(lián)就能得出結(jié)論一個(gè)rider框內(nèi)如果helmet框覆蓋了頭部區(qū)域判定為佩戴否則判定為未佩戴。這種設(shè)計(jì)的魯棒性遠(yuǎn)高于單純做二分類(lèi)。1.2 8300張的真實(shí)體感數(shù)據(jù)量夠不夠用先說(shuō)8300張這個(gè)規(guī)模。視頻抽幀做數(shù)據(jù)集的人都有概念一段10分鐘的25fps監(jiān)控視頻原始幀數(shù)是15000幀。但連續(xù)幀高度相似去重、清洗、挑不同角度和時(shí)段之后能留下幾百?gòu)堄行D就不錯(cuò)了。所以8300張如果來(lái)源是路口監(jiān)控、卡口抓拍、工地門(mén)口等多路視頻清洗篩選的工作量其實(shí)相當(dāng)可觀按人工標(biāo)注一小時(shí)50到80張的速度算光標(biāo)注就是100多個(gè)工時(shí)。這個(gè)量級(jí)對(duì)訓(xùn)練一個(gè)YOLO檢測(cè)模型來(lái)說(shuō)屬于夠用但不算富余。按常見(jiàn)的8:1:1劃分訓(xùn)練集約6600張驗(yàn)證集約830張測(cè)試集約830張。用預(yù)訓(xùn)練權(quán)重遷移學(xué)習(xí)在單張RTX 3090上訓(xùn)練100到150個(gè)epoch兩三個(gè)小時(shí)就能看到收斂趨勢(shì)。如果你的目標(biāo)不是刷學(xué)術(shù)榜單而是做一個(gè)能上線的交通檢測(cè)模型這個(gè)數(shù)據(jù)規(guī)模配YOLOv8s或YOLO11n完全夠用。當(dāng)然夠用是建立在數(shù)據(jù)質(zhì)量過(guò)關(guān)的前提下。8300張如果大量來(lái)自同一場(chǎng)景、同一時(shí)間段、同一角度那它實(shí)際的信息量會(huì)大打折扣。拿到數(shù)據(jù)集的第一件事不是急著開(kāi)訓(xùn)而是先做一通分布摸底——這個(gè)放到第二章細(xì)說(shuō)。2. 8300張圖怎么拆格式規(guī)范、類(lèi)別設(shè)計(jì)、場(chǎng)景分布評(píng)估2.1 YOLO標(biāo)注格式的底層邏輯YOLO格式的標(biāo)注不復(fù)雜但容易在細(xì)節(jié)上翻車(chē)。每張jpg圖片對(duì)應(yīng)一個(gè)同名的txt文件每一行代表一個(gè)目標(biāo)框格式是class_id x_center y_center width height其中x_center、y_center、width、height全部除以圖片寬高做了歸一化取值在0到1之間。舉個(gè)例子一張1920x1080的圖上一個(gè)人頭框左上角在(500, 300)寬200、高250那么歸一化后的值就是x_center (500 200 / 2) / 1920 0.3125 y_center (300 250 / 2) / 1080 0.3935 width 200 / 1920 0.1042 height 250 / 1080 0.2315我做數(shù)據(jù)檢查時(shí)一定會(huì)寫(xiě)個(gè)小腳本把所有txt掃描一遍檢查有沒(méi)有x_center width / 2 1或者坐標(biāo)出現(xiàn)負(fù)值的情況。這類(lèi)越界標(biāo)注在人工標(biāo)注時(shí)非常常見(jiàn)尤其當(dāng)目標(biāo)被畫(huà)面邊緣裁切時(shí)標(biāo)注員容易把框直接拉到畫(huà)面外。YOLO訓(xùn)練時(shí)這些異常框會(huì)報(bào)錯(cuò)或者被內(nèi)部算子靜默裁掉浪費(fèi)數(shù)據(jù)還干擾訓(xùn)練。2.2 類(lèi)別劃分三類(lèi)模型比二類(lèi)更實(shí)用頭盔檢測(cè)數(shù)據(jù)集通常有兩種類(lèi)別設(shè)計(jì)思路。一種只標(biāo)兩類(lèi)——with_helmet和without_helmet框住整個(gè)人由類(lèi)別區(qū)分有沒(méi)有戴。這種標(biāo)法快但問(wèn)題很明顯判斷依據(jù)是整人的語(yǔ)義而不是頭部區(qū)域當(dāng)畫(huà)面里同時(shí)出現(xiàn)戴頭盔和沒(méi)戴頭盔的兩個(gè)人挨得很近時(shí)模型容易學(xué)成按人周?chē)h(huán)境猜泛化能力差。另一種是標(biāo)三類(lèi)或四類(lèi)比如rider騎手、helmet頭盔、head未佩戴頭盔的頭部。模型輸出的邏輯更接近人眼判斷先看到人再看頭。這種數(shù)據(jù)集做出來(lái)的模型在業(yè)務(wù)層可以拿到人頭-頭盔配對(duì)關(guān)系方便接后續(xù)的跟蹤與取證邏輯。代價(jià)是標(biāo)注成本高、類(lèi)別間容易混淆——遠(yuǎn)處的人頭只有二三十像素標(biāo)rider還是head標(biāo)注員自己都可能猶豫。我比較推薦的是以三類(lèi)為底線rider、helmet、head。rider幫助模型把注意力集中在騎乘人員身上helmet和head再對(duì)頭部區(qū)域細(xì)分。這樣既保證了檢測(cè)穩(wěn)定性又為后續(xù)邏輯留出空間。2.3 拿到數(shù)據(jù)集先做場(chǎng)景摸底判斷一套數(shù)據(jù)集值不值得信任我一般看三張圖場(chǎng)景分布圖、目標(biāo)尺寸分布圖、類(lèi)別數(shù)量柱狀圖。場(chǎng)景分布上智慧交通頭盔檢測(cè)至少要覆蓋城市十字路口、非機(jī)動(dòng)車(chē)道、小區(qū)門(mén)口、工地/園區(qū)門(mén)口、地下停車(chē)場(chǎng)。如果全部來(lái)自同一品牌同一角度的槍機(jī)模型換一個(gè)場(chǎng)景就崩。目標(biāo)尺寸分布上頭盔檢測(cè)是典型的小目標(biāo)問(wèn)題——1080p畫(huà)面里遠(yuǎn)處的騎手頭部可能只有20x30像素而YOLO默認(rèn)的特征圖下采樣倍率是8、16、32太小目標(biāo)經(jīng)過(guò)多次下采樣后特征基本丟光。類(lèi)別數(shù)量上要看正負(fù)樣本比例如果未戴頭盔的樣本只有佩戴頭盔的十分之一訓(xùn)練時(shí)類(lèi)別傾向會(huì)非常明顯。這套8300張的數(shù)據(jù)集我建議你拿到后先用腳本統(tǒng)計(jì)一遍這些維度。如果發(fā)現(xiàn)夜間樣本偏少就自己補(bǔ)采一些夜間幀如果小目標(biāo)占比低后面的增強(qiáng)策略就要往放大、切圖方向傾斜。3. 模型選型為什么智慧交通場(chǎng)景繞不開(kāi)YOLO3.1 YOLO版本怎么選從v5到v8到v11頭盔檢測(cè)任務(wù)選擇YOLO不是因?yàn)樗钋把囟且驗(yàn)樗诰取⑺俣?、部署難度和社區(qū)生態(tài)之間做到了最好的平衡。以當(dāng)前主流版本為例YOLOv8是應(yīng)用最廣泛的選擇anchor-free設(shè)計(jì)讓回歸頭更簡(jiǎn)單C2f模塊在特征復(fù)用上比v5的C3更好解耦頭讓分類(lèi)和回歸任務(wù)不再互相干擾YOLO11也叫v11的Backbone和Neck做了進(jìn)一步優(yōu)化同等參數(shù)下mAP略高。YOLOv5雖然老了但生態(tài)成熟、文檔多仍有大量存量項(xiàng)目在用。我個(gè)人的選型習(xí)慣是邊緣設(shè)備Jetson、RK3588、海思等用n或s尺寸服務(wù)器單卡多路推流用s或m離線批量分析、對(duì)精度要求苛刻的場(chǎng)景用l或x以YOLOv8系列為例幾個(gè)版本的差距可以用一張表看明白模型參數(shù)量輸入尺寸mAP0.5 (COCO參考)單張1080p推理速度T4, FP16YOLOv8n3.2M640約37.3約2msYOLOv8s11.2M640約44.9約4msYOLOv8m25.9M640約50.2約7msYOLOv8l43.7M640約53.0約12ms對(duì)頭盔檢測(cè)這種小目標(biāo)居多的任務(wù)我建議從s起步在RTX 3090上把完整流程跑通再根據(jù)部署硬件裁剪到n或升到m。一上來(lái)就用x訓(xùn)練慢、部署難實(shí)際收益卻不一定大。3.2 為什么不選Faster R-CNN或DETR不是說(shuō)兩階段檢測(cè)器和Transformer檢測(cè)器沒(méi)有優(yōu)勢(shì)——Faster R-CNN在小目標(biāo)上的歷史表現(xiàn)確實(shí)不差但其推理速度在幾十路視頻面前毫無(wú)競(jìng)爭(zhēng)力DETR類(lèi)模型在同等數(shù)據(jù)量下訓(xùn)練不穩(wěn)定收斂需要的epoch更多而且部署鏈路上TensorRT的適配成熟度參差不齊。智慧交通項(xiàng)目的核心約束是幾十路視頻同時(shí)跑每路25幀這種情況下每幀5ms和每幀50ms的差距是決定性的。當(dāng)然如果數(shù)據(jù)集只有一兩百?gòu)垐DYOLO也很難發(fā)揮那種極端情況更適合用成熟的第三方模型直接做零樣本推理而不是自己從頭訓(xùn)。3.3 預(yù)訓(xùn)練權(quán)重遷移別從零開(kāi)始頭盔是自然圖像里的常見(jiàn)物體但在ImageNet或COCO上預(yù)訓(xùn)練過(guò)的模型并不會(huì)天生理解頭盔這個(gè)概念。你做的遷移學(xué)習(xí)是利用它在海量自然圖上學(xué)會(huì)的紋理、邊緣、形狀等基礎(chǔ)特征然后在自己的數(shù)據(jù)集上微調(diào)。實(shí)操時(shí)下載YOLOv8官方提供的yolov8s.pt作為初始權(quán)重設(shè)置pretrainedTrue訓(xùn)練時(shí)會(huì)自動(dòng)加載。這里有個(gè)細(xì)節(jié)如果你的類(lèi)別數(shù)量和數(shù)據(jù)集的類(lèi)別數(shù)量不一致訓(xùn)練框架會(huì)自動(dòng)丟棄原模型最后一層的分類(lèi)頭隨機(jī)初始化新的分類(lèi)頭所以你只需要關(guān)心backbone和neck部分的遷移效果。4. 說(shuō)出來(lái)你可能不信訓(xùn)練流程里最花時(shí)間的其實(shí)是數(shù)據(jù)準(zhǔn)備4.1 目錄結(jié)構(gòu)與data.yaml拿到數(shù)據(jù)集后我習(xí)慣先規(guī)整目錄。YOLO訓(xùn)練的標(biāo)準(zhǔn)目錄結(jié)構(gòu)是這樣的helmet_dataset/ ├── train/ │ ├── images/ │ │ ├── 0001.jpg │ │ └── ... │ └── labels/ │ ├── 0001.txt │ └── ... ├── val/ │ ├── images/ │ └── labels/ └── test/ ├── images/ └── labels/然后寫(xiě)一個(gè)data.yamlpath: /path/to/helmet_dataset train: train/images val: val/images test: test/images nc: 3 names: [rider, helmet, head]如果你的數(shù)據(jù)集里所有圖都還堆在一起需要先寫(xiě)腳本劃分目錄。我習(xí)慣按9:0.5:0.5劃分訓(xùn)練驗(yàn)證測(cè)試再用隨機(jī)種子固定結(jié)果保證每次復(fù)現(xiàn)一致。劃分時(shí)有一個(gè)經(jīng)驗(yàn)先用一個(gè)腳本統(tǒng)計(jì)每一幀圖片的拍攝時(shí)間戳或文件名hash保證同一段連續(xù)視頻的幀不要同時(shí)落在訓(xùn)練集和測(cè)試集里否則測(cè)試指標(biāo)會(huì)被嚴(yán)重高估——模型記憶的是場(chǎng)景不是目標(biāo)本身。4.2 訓(xùn)練參數(shù)這些值怎么定訓(xùn)練頭盔檢測(cè)模型我常用的參數(shù)基線如下yolo detect train \ datadata.yaml \ modelyolov8s.pt \ pretrainedTrue \ epochs150 \ imgsz640 \ batch16 \ device0 \ optimizerAdamW \ lr00.001 \ mosaic1.0 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4每個(gè)參數(shù)都不是隨便拍的。imgsz640是YOLO的黃金輸入尺寸精度和速度的平衡點(diǎn)如果小目標(biāo)多我會(huì)先試imgsz768通過(guò)提升輸入分辨率讓頭盔占更多像素通常mAP能漲2到3個(gè)點(diǎn)。batch16在16G顯存的卡上比較穩(wěn)如果你顯存只有8G就降到8或4。mosaic1.0是數(shù)據(jù)增強(qiáng)里的核心武器它把四張圖拼成一張讓模型在一個(gè)batch里看到更多樣的場(chǎng)景、更多尺度的目標(biāo)對(duì)頭盔這種小目標(biāo)場(chǎng)景幫助極大。hsv系列的擾動(dòng)模擬了不同光照條件尤其能彌補(bǔ)夜間樣本不足的短板。關(guān)于訓(xùn)練輪數(shù)我不建議無(wú)腦設(shè)置300個(gè)epoch。先用150跑通看訓(xùn)練日志里的val/box_loss、val/cls_loss、val/dfl_loss是否在最后20個(gè)epoch還在下降。如果val損失連續(xù)30個(gè)epoch沒(méi)有明顯變化說(shuō)明已經(jīng)收斂再多的epoch只會(huì)過(guò)擬合。頭盔檢測(cè)的數(shù)據(jù)量不算海量數(shù)據(jù)集8300張訓(xùn)150輪已經(jīng)能拿到一個(gè)不錯(cuò)的模型。4.3 損失函數(shù)與評(píng)估指標(biāo)怎么讀YOLOv8的損失由三部分組成box_loss回歸損失用CIoU計(jì)算、cls_loss分類(lèi)損失用BCE計(jì)算、dfl_loss分布焦點(diǎn)損失用來(lái)細(xì)化邊界框。訓(xùn)練時(shí)你會(huì)看到三個(gè)loss在results.csv里分別記錄。我對(duì)loss曲線的要求是訓(xùn)練集三個(gè)loss穩(wěn)步下降驗(yàn)證集三個(gè)loss在下降后進(jìn)入平臺(tái)期。如果驗(yàn)證集loss在某個(gè)epoch后開(kāi)始反彈說(shuō)明過(guò)擬合開(kāi)始。評(píng)估指標(biāo)主要看mAP0.5和mAP0.5:0.95。前者是IoU閾值取0.5時(shí)的平均精度后者是0.5到0.95每隔0.05取一組IoU閾值的平均。對(duì)頭盔檢測(cè)這種框大一點(diǎn)小一點(diǎn)都不致命的任務(wù)我會(huì)優(yōu)先盯mAP0.5能達(dá)到90%以上算合格mAP0.5:0.95則是模型定位精度的硬指標(biāo)一般60%到70%就說(shuō)明邊界框已經(jīng)壓得很準(zhǔn)了。還有一份必看的輸出是confusion_matrix.png。如果發(fā)現(xiàn)head被大量誤檢成helmet說(shuō)明兩者在特征空間里的距離太近可能需要更細(xì)致的標(biāo)注或更高質(zhì)量的訓(xùn)練圖如果未佩戴樣本大量漏檢大概率是訓(xùn)練集里未佩戴樣本的比例偏低需要補(bǔ)數(shù)據(jù)或調(diào)類(lèi)別權(quán)重。4.4 可視化驗(yàn)證訓(xùn)練完一定要看bad case模型訓(xùn)完我會(huì)寫(xiě)一個(gè)推理腳本把測(cè)試集預(yù)測(cè)結(jié)果畫(huà)出來(lái)逐張看。這一步花不了半小時(shí)卻能暴露指標(biāo)看不出的問(wèn)題。比如模型把車(chē)筐里的頭盔當(dāng)成佩戴頭盔把路旁的安全帽當(dāng)成rider的頭盔這些在mAP上其實(shí)都會(huì)體現(xiàn)為誤檢框但只有肉眼看圖才能快速定位原因。我見(jiàn)過(guò)不少團(tuán)隊(duì)訓(xùn)練完只看mAP數(shù)字覺(jué)得90%就上線了結(jié)果在真實(shí)路口的監(jiān)控畫(huà)面上被各種奇怪物體打到滿地是框??梢暬?yàn)證這一關(guān)不能省。5. 要命的高頻踩坑小目標(biāo)、夜間低光、標(biāo)注噪聲5.1 小目標(biāo)漏檢頭盔檢測(cè)最大的痛點(diǎn)頭盔檢測(cè)和普通目標(biāo)檢測(cè)最大的不同是頭盔在畫(huà)面里太小了。1080p畫(huà)面里一個(gè)10米外的騎手頭部可能只占30x30像素而YOLO的默認(rèn)檢測(cè)層是P38倍下采樣、P416倍、P532倍經(jīng)過(guò)8倍下采樣后30x30的目標(biāo)只剩約4x4個(gè)特征點(diǎn)信息損失嚴(yán)重。我在第一個(gè)版本就踩了這個(gè)坑訓(xùn)練集mAP0.5有91%但實(shí)際測(cè)試中畫(huà)面遠(yuǎn)處騎手幾乎全部漏檢。排查的思路是分三步把所有漏檢目標(biāo)框統(tǒng)計(jì)出來(lái)算它們的面積分布確認(rèn)是否集中在極小尺寸區(qū)間。直接把輸入分辨率提高到768或960看看漏檢率是否明顯下降。使用切圖推理SAHI把1080p原圖切成兩三個(gè)640x640的子圖分別檢測(cè)再合并結(jié)果。實(shí)際操作下來(lái)提高輸入分辨率效果最直接但推理變慢切圖推理效果極好但每路視頻的推理時(shí)間會(huì)翻倍。折中方案是線上用640輸入配合NMS后處理優(yōu)化線下分析或取證場(chǎng)景用切圖離線刷一遍。還有一個(gè)思路是給模型加P2檢測(cè)頭。YOLOv8官方支持自定義head結(jié)構(gòu)在P2層4倍下采樣增設(shè)一個(gè)檢測(cè)頭專(zhuān)門(mén)負(fù)責(zé)小目標(biāo)。代價(jià)是計(jì)算量上升、訓(xùn)練變慢但小目標(biāo)的召回率確實(shí)能漲。5.2 夜間低光數(shù)據(jù)增強(qiáng)救不了一切頭盔檢測(cè)的夜間場(chǎng)景是所有智慧交通項(xiàng)目繞不過(guò)去的坎。監(jiān)控?cái)z像頭在夜間的畫(huà)面要么是紅外的黑白圖像要么是低照度彩噪圖。如果你訓(xùn)練集里沒(méi)有這類(lèi)樣本白天的模型放到晚上幾乎等于失明。我遇到過(guò)最狼狽的一次模型在白天測(cè)試mAP 93%結(jié)果現(xiàn)場(chǎng)驗(yàn)收是晚上整個(gè)畫(huà)面全黑模型輸出了幾百個(gè)毫無(wú)意義的低置信框。后來(lái)總結(jié)經(jīng)驗(yàn)夜間問(wèn)題的解法有三個(gè)方向按見(jiàn)效程度排序補(bǔ)采真實(shí)的夜間/黃昏數(shù)據(jù)讓模型直接見(jiàn)過(guò)這個(gè)光照分布。沒(méi)有條件補(bǔ)采就從現(xiàn)有視頻里抽取低光幀用Gamma校正模擬夜間效果。用圖像增強(qiáng)技術(shù)如HE、CLAHE對(duì)夜間幀做預(yù)處理讓單幀的紋理更明顯再送進(jìn)檢測(cè)器。如果監(jiān)控?cái)z像頭本身就是紅外夜視訓(xùn)練時(shí)把圖像轉(zhuǎn)成灰度或使用IR風(fēng)格化的增強(qiáng)讓模型適應(yīng)單通道紋理。我個(gè)人強(qiáng)烈建議不管數(shù)據(jù)集多好落地前一定要找?guī)锥文繕?biāo)場(chǎng)景的真實(shí)夜間視頻哪怕只有幾百幀跑一遍看效果。夜間模型翻車(chē)幾乎都是因?yàn)橛?xùn)練分布和部署分布不一致。5.3 標(biāo)注噪聲漏標(biāo)和錯(cuò)標(biāo)比想象中更致命8300張數(shù)據(jù)集的標(biāo)注質(zhì)量參差不齊這是常態(tài)。最常見(jiàn)的標(biāo)注問(wèn)題是密集場(chǎng)景漏標(biāo)注一排等紅燈的騎手標(biāo)注員只標(biāo)了兩三個(gè)其余全部漏掉。模型學(xué)到騎手周?chē)梢杂形礃?biāo)注目標(biāo)推理時(shí)就會(huì)抑制本該輸出的框。遮擋目標(biāo)只標(biāo)可見(jiàn)部分一個(gè)騎手被汽車(chē)擋住一半標(biāo)注框只框住了露出的一小半身體導(dǎo)致模型對(duì)半身rider產(chǎn)生了錯(cuò)誤先驗(yàn)。類(lèi)別混淆遠(yuǎn)處的head被標(biāo)成helmet或者反過(guò)來(lái)。排查標(biāo)注噪聲核心手段是訓(xùn)練前可視化。我把所有訓(xùn)練圖的標(biāo)注畫(huà)出來(lái)輸出成一張大拼圖然后快速翻看。這個(gè)方法雖然土但效率極高。還有一個(gè)技巧訓(xùn)練一個(gè)基線模型后把置信度極高的誤檢框和置信度極低的漏檢圖挑出來(lái)和原圖標(biāo)注對(duì)比如果發(fā)現(xiàn)模型認(rèn)為有目標(biāo)但標(biāo)注里沒(méi)有大概率是標(biāo)注漏了。5.4 類(lèi)別不平衡別急著調(diào)loss權(quán)重頭盔數(shù)據(jù)集里未戴頭盔的樣本天然偏少因?yàn)榇蠖鄶?shù)騎手還是守規(guī)矩的。類(lèi)別不平衡會(huì)導(dǎo)致召回率偏向多數(shù)類(lèi)。但我建議不要一上來(lái)就調(diào)cls_loss的權(quán)重或強(qiáng)行加負(fù)樣本那樣容易讓模型在騎手和頭盔的判斷上變得猶猶豫豫。優(yōu)先做的是把已有的少數(shù)類(lèi)樣本復(fù)制一份配合隨機(jī)幾何變換翻轉(zhuǎn)、旋轉(zhuǎn)、縮放生成合成樣本相當(dāng)于給少數(shù)類(lèi)做了過(guò)采樣同時(shí)不改變語(yǔ)義。如果補(bǔ)完數(shù)據(jù)后依然不平衡再考慮在loss里給少數(shù)類(lèi)加權(quán)重也不遲。6. 從模型到上線TensorRT加速與多路監(jiān)控的工程化6.1 導(dǎo)出與加速pt到onnx再到engine訓(xùn)練完成的.pt權(quán)重只是一個(gè)訓(xùn)練產(chǎn)物直接拿來(lái)推理可以但效率和穩(wěn)定性都不適合生產(chǎn)環(huán)境。我通常的導(dǎo)出鏈路是yolo export modelbest.pt formatonnx dynamicTrue opset12然后通過(guò)TensorRT把onnx轉(zhuǎn)成engine。以YOLOv8為例可以用官方提供的trtexec或tensorrt_yolo項(xiàng)目完成轉(zhuǎn)換。FP16精度對(duì)精度影響很小推理速度能比FP32快一倍以上INT8還要做校準(zhǔn)集標(biāo)定精度損失不確定我一般只在極端邊緣設(shè)備上才用。轉(zhuǎn)換過(guò)程中有一個(gè)高頻坑dynamic shape。如果你的部署場(chǎng)景輸入尺寸固定比如統(tǒng)一640x640那直接關(guān)閉dynamic用固定shape轉(zhuǎn)省心省力還快如果必須支持不同輸入尺寸再把-1維度的動(dòng)態(tài)范圍配好。TensorRT 8.x以上版本對(duì)YOLO的插件支持已經(jīng)比較成熟但不同版本之間的兼容性還是要反復(fù)驗(yàn)證。6.2 多路視頻實(shí)測(cè)25幀1080p的算力估算在實(shí)際智慧交通項(xiàng)目里支持多少路視頻幾乎是甲方必問(wèn)的問(wèn)題。以一個(gè)典型配置估算T4 GPUTensorRT FP16YOLOv8s輸入640x640單幀推理大約4到6ms。如果只算推理理論上每秒能處理160到250幀即6到10路25fps的1080p視頻。但這只是理論值。實(shí)際工程里每路視頻都要先解碼——1080p H.264解碼本身也吃GPU或CPU資源檢測(cè)后還有跟蹤器ByteTrack/DeepSORT、業(yè)務(wù)邏輯判斷、抓拍入庫(kù)、告警推送這些都要占用算力。所以工程上都留有余量單張T4跑6到8路25fps比較穩(wěn)。再往上就要上DeepStream這類(lèi)硬解多路解碼框架或者用多卡分負(fù)載。這里啰嗦一句YOLO推理時(shí)間和視頻解碼時(shí)間經(jīng)常被分頭評(píng)估但真正上線時(shí)它們共享同一塊顯存和PCIe帶寬內(nèi)存帶寬競(jìng)爭(zhēng)比你想的更嚴(yán)重。批量推理時(shí)把多路視頻幀拼成一個(gè)batch能有效攤薄調(diào)度開(kāi)銷(xiāo)這是摸過(guò)性能瓶頸的人都會(huì)做的事。6.3 業(yè)務(wù)閉環(huán)檢測(cè)之后的路頭盔檢測(cè)模型只是系統(tǒng)里的一個(gè)組件。完整業(yè)務(wù)閉環(huán)一般是攝像頭視頻流 → 解碼抽幀 → 目標(biāo)檢測(cè)rider/helmet/head → 多目標(biāo)跟蹤ByteTrack關(guān)聯(lián)跨幀同一人 → 業(yè)務(wù)規(guī)則判斷rider框內(nèi)是否有helmet覆蓋頭部區(qū)域 → 觸發(fā)抓拍、取證、上報(bào)。跟蹤環(huán)節(jié)容易被忽略但非常重要。單幀檢測(cè)結(jié)果波動(dòng)大同一輛車(chē)在連續(xù)幾幀里可能一幀檢出一幀漏掉。用ByteTrack做ID關(guān)聯(lián)后可以在一個(gè)ID的連續(xù)軌跡上做幀級(jí)投票——超過(guò)70%的幀判定為未佩戴才觸發(fā)告警能極大降低誤報(bào)率。我在實(shí)際項(xiàng)目里還加了一個(gè)緩沖機(jī)制檢測(cè)到未佩戴后延遲2秒再抓拍目的是等車(chē)輛行駛到畫(huà)面中央、目標(biāo)尺寸最大的時(shí)刻再取證避免拍到一張幾十像素的模糊人影。工程上還有兩個(gè)實(shí)用細(xì)節(jié)。一是原始視頻幀要保存至少7天便于事后復(fù)核和模型迭代時(shí)回放bad case。二是告警圖片的水印和坐標(biāo)信息抓拍時(shí)間、地點(diǎn)、車(chē)牌、置信度要在檢測(cè)端就寫(xiě)入不能在云端二次處理時(shí)丟失。前者是運(yùn)維需要后者是取證合規(guī)需要。最后分享一個(gè)小技巧是我做頭盔檢測(cè)迭代三輪之后總結(jié)出來(lái)的先用小模型n/s尺寸以最快速度跑通整個(gè)鏈路拿到真實(shí)場(chǎng)景的bad case再用大模型m/l尺寸離線批量刷歷史監(jiān)控視頻把所有誤檢、漏檢幀自動(dòng)抽出來(lái)回填到訓(xùn)練集重新訓(xùn)練。這個(gè)小模型圈定問(wèn)題、大模型補(bǔ)充數(shù)據(jù)的循環(huán)跑兩到三輪模型的真實(shí)場(chǎng)景mAP提升比單純調(diào)參明顯得多。數(shù)據(jù)、模型、部署三者互相喂才是把一套公開(kāi)數(shù)據(jù)集真正變成可落地系統(tǒng)的正確姿勢(shì)。