實戰(zhàn):YOLOv8訓(xùn)練與TensorRT邊緣部署)
做過圖像識別方向的朋友應(yīng)該都清楚垃圾分類檢測系統(tǒng)這幾年幾乎成了計算機視覺入門項目的標(biāo)配。但真正把它從跑通一個Demo做到能在現(xiàn)場穩(wěn)定工作中間隔著的距離比大多數(shù)人想象的要遠。這篇文章我想完整梳理一遍我實際搭建一套垃圾分類檢測系統(tǒng)的全過程包括數(shù)據(jù)集怎么搞、模型怎么選、訓(xùn)練參數(shù)怎么調(diào)、部署到邊緣設(shè)備時踩了哪些坑以及最后聯(lián)動機械結(jié)構(gòu)讓檢測結(jié)果真正驅(qū)動分類動作的關(guān)鍵細節(jié)。內(nèi)容適合正在做課程設(shè)計、畢業(yè)設(shè)計或者想用視覺方案解決實際分揀問題的朋友參考我會把能直接復(fù)用的經(jīng)驗和教訓(xùn)都寫出來。先說清楚這套系統(tǒng)解決的實際問題社區(qū)投放點、校園分類垃圾桶、小型回收站里人工分揀效率低且一致性差尤其廚余垃圾混入可回收物之后整桶可回收物的價值都會大打折扣。視覺檢測方案的核心就是把人眼判斷替換成攝像頭加模型判斷在垃圾進入對應(yīng)桶之前完成類別識別和數(shù)據(jù)上報。下面直接進入正題。1. 為什么一個攝像頭加一塊板子就能重新定義垃圾分類1.1 先搞清楚這個系統(tǒng)到底解決誰的什么問題我開始做這個項目之前先列了一份需求清單而不是急著找數(shù)據(jù)集。不同場景對檢測系統(tǒng)的要求差異非常大社區(qū)智能分類桶識別對象是居民手持的垃圾袋或單件垃圾要求識別速度快、支持品類多但精度要求相對寬松因為還有人工復(fù)核環(huán)節(jié)。小型回收站分揀線傳送帶上連續(xù)過檢要求高吞吐、低延遲誤判會直接影響回收物純度對精度要求苛刻。校園/園區(qū)示范點更看重交互體驗和趣味性經(jīng)常需要語音反饋、屏幕展示檢測只是整個交互鏈路的一環(huán)。我最終定位在可落地到社區(qū)和校園的輕量級檢測終端這個方向上核心指標(biāo)就是兩個單幀推理延遲不超過100毫秒常見單件垃圾的分類準(zhǔn)確率在90%以上。這個目標(biāo)不高不低既不會讓模型選型過于痛苦又能真實跑通業(yè)務(wù)閉環(huán)。1.2 四分類體系下的檢測難度分層國內(nèi)垃圾分類通用體系是四分類可回收物、有害垃圾、廚余垃圾、其他垃圾。但直接把這四類作為模型輸出類別模型會非常困惑——因為可回收物內(nèi)部包含塑料瓶、紙箱、玻璃瓶、易拉罐外觀差異極大廚余垃圾在圖像上則往往是形態(tài)不規(guī)則、顏色雜亂的混合物。這個項目我沒法用README或教程里的通用說法糊弄自己必須明確模型真正要學(xué)的是物理單品而不是抽象分類。所以我采用的是兩級結(jié)構(gòu)檢測模型先識別出具體物品比如礦泉水瓶紙板箱玻璃瓶再由規(guī)則引擎映射到四分類的最終結(jié)果。這樣做的好處是訓(xùn)練目標(biāo)清晰、誤判鏈路可追溯排查為什么這瓶醬油被分進了有害垃圾這類問題時能直接定位是檢測錯了還是映射規(guī)則錯了。2. 數(shù)據(jù)準(zhǔn)備比想象中更磨人采集、清洗與標(biāo)注的血淚清單2.1 每類垃圾該準(zhǔn)備多少張圖才有底氣很多教程會告訴你每類500張就能訓(xùn)練但這話只說對了一半。500張的前提是背景多樣、視角多樣、光照多樣如果500張全是同一塊灰色背景布上拍的俯視圖模型的泛化能力會非常差。我的實踐標(biāo)準(zhǔn)是每個目標(biāo)類別至少800張真實場景圖像其中包含至少5種不同背景、3種不同拍攝高度、白天和夜間各占一部分比例。優(yōu)先級最高的是真實投放場景的圖像——垃圾桶旁邊、傳送帶上、水泥地上這些才是推理時真正會遇到的環(huán)境。類別數(shù)量上我選了12個常見單品礦泉水瓶、易拉罐、玻璃瓶、紙板箱、報紙、塑料袋、一次性餐盒、果皮、剩菜、電池、燈管、煙蒂。12類覆蓋了四分類體系中80%以上的常見投放場景又不至于讓標(biāo)注工作量翻倍。2.2 標(biāo)注規(guī)范邊界框怎么打才能讓模型少犯迷糊標(biāo)注工具我用的LabelStudio支持矩形框和標(biāo)簽管理比LabelImg順手一些多人協(xié)作時可以用Web端統(tǒng)一管理標(biāo)注進度。但工具只是輔助真正決定模型上限的是標(biāo)注規(guī)范。我制定了幾條硬性規(guī)則遮擋超過50%的物體不標(biāo)注寧可漏掉也不給模型錯誤的監(jiān)督信號。對于彎曲、折疊的物體塑料袋、報紙用貼近可見區(qū)域輪廓的矩形框不要把大量空白背景框進來。同一張圖里的多個同類物體全部獨立標(biāo)注不能只標(biāo)一個。模糊到人眼都難判斷類別的圖直接刪除不納入訓(xùn)練集。這幾條規(guī)則執(zhí)行完之后訓(xùn)練出來的模型邊界框明顯更緊實誤檢率也下降了不少。反而是我最早犯的錯——為了追求數(shù)量把大量模糊圖、嚴(yán)重遮擋圖也標(biāo)進去——導(dǎo)致loss怎么調(diào)都降不下去。2.3 數(shù)據(jù)質(zhì)量檢查被忽略的高重復(fù)樣本陷阱標(biāo)注完成之后一定要做重復(fù)樣本檢查。我的訓(xùn)練集里一度存在大量從視頻中連續(xù)抽幀得到的圖像相鄰幀之間只有微小位移模型在訓(xùn)練時會反復(fù)看到幾乎一樣的樣本相當(dāng)于變相放大了這類樣本的權(quán)重導(dǎo)致真實場景下的泛化能力變差。處理方式其實簡單對每個類別按感知哈希去重相似度高于閾值的只保留一張再按拍攝場景做一次分層抽樣確認。這一步花不了多少時間但對訓(xùn)練效果的影響是決定性的。清洗之后我從12類共9600張圖壓縮到了7200張左右訓(xùn)練出來的模型反而更穩(wěn)了。3. 模型選型與訓(xùn)練調(diào)參我為什么鎖死YOLOv8而不是去追新3.1 檢測框架橫向?qū)Ρ萗OLO系列、SSD、Faster R-CNN檢測模型的選擇會直接影響后續(xù)所有工作這里值得多花點篇幅說清楚。我把主流方案放在一張表里對比過模型框架推理速度精度表現(xiàn)部署難度社區(qū)資料豐富度Faster R-CNN慢數(shù)百毫秒級高較高多但偏學(xué)術(shù)SSD較快中小目標(biāo)一般中等一般YOLOv5快較高低非常多YOLOv8快較高且均衡低多官方支持完善YOLOv9/v11更快高中等相對較少對于垃圾分類這個場景目標(biāo)通常不算小單件垃圾占畫面比例較大不需要極端的小目標(biāo)檢測能力更需要的是部署方便、社區(qū)案例多、踩坑有人分享。YOLOv8的ultralytics框架把訓(xùn)練、驗證、導(dǎo)出封裝得很完整一套API走到底所以我最終選了YOLOv8n作為主力模型在保證精度的前提下把體積壓到最小。后來我也看到有人用更新版本的YOLO做類似項目起點更高但遇到問題時能參考的資料少很多。如果你追求的是項目穩(wěn)妥完成而不是發(fā)論文選資料最全的方案永遠是最優(yōu)解。3.2 訓(xùn)練環(huán)境與關(guān)鍵超參的取值邏輯訓(xùn)練用的是單張消費級顯卡顯存8GB這個配置跑YOLOv8n沒有任何壓力。環(huán)境直接用ultralytics的pip包PyTorch 2.x配合CUDA 11.8Python版本3.10。整個環(huán)境搭建半小時內(nèi)搞定。關(guān)鍵超參我是這么取的每個數(shù)值背后都有理由輸入分辨率640×640YOLOv8的默認值對單件垃圾足夠再往上提會明顯拉慢推理速度。batch size 168GB顯存下能穩(wěn)定跑滿再大會爆顯存。epochs 150在小數(shù)據(jù)集上訓(xùn)練150輪足夠讓模型收斂我觀察loss曲線在100輪附近就基本平了。學(xué)習(xí)率0.01配合ultralytics自帶的余弦退火調(diào)度從頭訓(xùn)練時這個值比較穩(wěn)不會出現(xiàn)起步震蕩。mosaic增強開啟把4張圖拼成一張訓(xùn)練能顯著改善模型對小目標(biāo)的魯棒性后期我在最后20輪關(guān)閉了mosaic讓模型適應(yīng)真實的單目標(biāo)分布。訓(xùn)練命令就是一行yolo detect train datawaste.yaml modelyolov8n.pt epochs150 imgsz640 batch16 device0waste.yaml里的路徑和類別名我在開始訓(xùn)練前反復(fù)核對過因為類別順序一旦錯了后面所有評估結(jié)果都會跟著錯。3.3 訓(xùn)練過程中必須盯住的三個信號訓(xùn)練不是把命令敲完就完事了。我每隔一段時間就看三個指標(biāo)box_loss持續(xù)下降但cls_loss震蕩說明模型在學(xué)定位但類別區(qū)分吃力大概率是數(shù)據(jù)問題回頭檢查有沒有類別樣本量失衡。驗證集mAP50達到0.95以上但mAP50-95只有0.6出頭說明檢測框大致位置對但框的精細度不夠可以試試增大輸入分辨率或者調(diào)整置信度閾值。某個類別單獨拉出來AP特別低幾乎可以斷定這類樣本的多樣性不足優(yōu)先補數(shù)據(jù)而不是調(diào)參。我的最終結(jié)果12類平均mAP50達到0.97其中燈管和煙蒂這兩類稍低一個因為透明材質(zhì)難分辨一個因為個體太小。這兩類的優(yōu)化思路我放在后面第5章展開。4. 從訓(xùn)練機到分揀現(xiàn)場模型壓縮與部署的全過程4.1 ONNX導(dǎo)出與TensorRT加速的實際收益模型訓(xùn)練完只是第一步要在邊緣設(shè)備上達到實時推理必須做模型轉(zhuǎn)換和加速。我先后試過三種導(dǎo)出方式直接PyTorch推理延遲約180毫秒顯存占用偏高不滿足實時要求。ONNX導(dǎo)出加CPU推理延遲降到約280毫秒反而更慢原因是CPU上的ONNXRuntime對YOLOv8結(jié)構(gòu)中的某些算子優(yōu)化一般。ONNX導(dǎo)出加TensorRTFP16精度延遲穩(wěn)定在45毫秒左右GPU利用率和功耗表現(xiàn)都可接受。TensorRT的加速效果非常明顯但配置過程有些繁瑣需要根據(jù)顯卡型號下載對應(yīng)版本的TensorRT包再通過trtexec工具把ONNX模型編譯成engine文件。我用的是一塊嵌入式GPU開發(fā)板顯存不大FP16量化后模型體積從14MB縮到7MB左右精度損失不到1個百分點完全在可接受范圍內(nèi)。導(dǎo)出命令參考yolo export modelbest.pt formatonnx dynamicTrue trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp164.2 實時推理流水線的工程細節(jié)模型推理只是流水線的一環(huán)。完整的實時檢測流程是攝像頭采集圖像 → 圖像預(yù)處理縮放、歸一化 → TensorRT推理 → 后處理解碼檢測框、NMS去除重疊框 → 輸出類別和坐標(biāo)。最容易出問題的是預(yù)處理環(huán)節(jié)。訓(xùn)練時的數(shù)據(jù)增強里包含了隨機色域變換但推理時不能做這些必須用固定的歸一化參數(shù)否則會出現(xiàn)訓(xùn)練時好好的一上線準(zhǔn)確率暴跌的詭異問題。我在預(yù)處理里嚴(yán)格復(fù)用了訓(xùn)練時的letterbox參數(shù)保持長寬比縮放到640×640剩余部分用灰色填充這樣才不會讓圖像變形影響檢測。后處理里的置信度閾值我調(diào)到0.35NMS的IoU閾值保持默認的0.7。置信度閾值太低會出現(xiàn)大量誤檢框太高又會漏掉重疊擺放的垃圾0.35是比較均衡的值。4.3 聯(lián)動硬件讓檢測結(jié)果真正驅(qū)動分類動作檢測系統(tǒng)要真正服務(wù)于分類不能停在屏幕上畫個框這個層面。我做了一個聯(lián)動方案當(dāng)檢測到某件垃圾的置信度超過閾值時通過串口向分揀控制板發(fā)送類別指令控制板驅(qū)動對應(yīng)垃圾桶的翻板機構(gòu)完成投放。這塊的通信協(xié)議是最容易被人忽略的細節(jié)。我定義了一個極簡的ASCII協(xié)議格式是SCL:類別ID;置信度;時間戳\n??刂瓢褰馕龅絊CL:3;0.96;1714000000這樣的幀之后確認類別ID合法就執(zhí)行翻板動作否則丟棄并記錄日志。協(xié)議里加時間戳的原因是為了事后排查哪一幀圖像對應(yīng)哪一次分揀動作在聯(lián)調(diào)時幫了大忙。攝像頭到控制板的整體時延分配大概是采集加預(yù)處理10毫秒推理45毫秒串口傳輸加機械動作300毫秒左右。對于日常投放場景這個響應(yīng)速度完全夠用。5. 實測翻車實錄相似垃圾、光照干擾和遮擋難題5.1 最頭疼的誤判透明塑料瓶與玻璃瓶實測中遇到最多的誤判案例就是透明礦泉水瓶和透明玻璃瓶。兩者在外觀上高度相似——都是透明、圓柱形、有反光——人眼有時都要湊近了才能分辨模型更是經(jīng)常把它們混在一起。我一開始嘗試在模型層面強行區(qū)分降低置信度閾值、增加這兩類的樣本量效果都不理想。后來換了個思路不再讓視覺模型硬扛全部判斷而是在透明瓶類別的置信度落在模糊區(qū)間比如0.4到0.7時觸發(fā)一次額外的材質(zhì)判定邏輯——通過目標(biāo)區(qū)域的顏色直方圖和紋理特征做個二次判斷。雖然仍然是圖像層面的啟發(fā)式規(guī)則但實測把這兩類的混淆率降低了40%以上。這件事給我的啟發(fā)是不是所有問題都該用模型解決。合理的規(guī)則兜底比盲目加數(shù)據(jù)更高效。5.2 光照變化讓準(zhǔn)確率坐了過山車晴天中午的強光、傍晚的暖色燈光、室內(nèi)的熒光燈不同光照條件下同一件垃圾在圖像里的表現(xiàn)差異很大。我的模型在室內(nèi)燈光下mAP50到了0.97拿到戶外強光下一測直接掉到0.88這個落差讓我意識到訓(xùn)練數(shù)據(jù)里戶外樣本太少。補救措施分兩層。第一層是最直接的數(shù)據(jù)層面補充了大量逆光和強曝光場景下的樣本并且在增強策略里加大了對亮度擾動和HSV色域擾動的力度。第二層是硬件層面在部署現(xiàn)場的投放口增加了補光燈讓相機看到的畫面亮度盡量穩(wěn)定。補光的思路是從安防攝像頭那里學(xué)來的——盡量改變環(huán)境去適配模型而不是無限提高模型對環(huán)境變化的魯棒性。5.3 難例挖掘與針對性增強的補救措施針對煙蒂這類小目標(biāo)檢測弱的問題我做了三件事把訓(xùn)練數(shù)據(jù)里煙蒂所在的圖片集中挑出來統(tǒng)計它們的真實尺寸占比發(fā)現(xiàn)普遍小于畫面的3%屬于小目標(biāo)范疇。在數(shù)據(jù)增強中增加了隨機裁切放大將小目標(biāo)區(qū)域裁出來放大后再拼回原圖強制模型去學(xué)習(xí)小目標(biāo)的特征。將mosaic增強的強度在小目標(biāo)類別上稍微提高了比例讓模型在訓(xùn)練中看到更多小尺寸的正樣本。這三步走完煙蒂的AP從0.78提到了0.91。雖然還是12類里最低的但實際使用中已經(jīng)不容易漏檢了。難例挖掘的通用方法論其實就是一句話把模型最容易犯錯的樣本找出來分析它們?yōu)槭裁村e再針對性地讓它們在訓(xùn)練中出現(xiàn)得更頻繁。6. 更遠一步從單幀檢測到完整的分揀閉環(huán)6.1 硬件選型與成本控制的思考整套系統(tǒng)的成本大頭在算力板和攝像頭。算力板我最終用的是嵌入式GPU開發(fā)板功耗低、支持TensorRT單塊成本在幾百元到千元這個區(qū)間適合批量部署。如果只做算法驗證用普通電腦加USB攝像頭就夠了成本能壓到最低。攝像頭選型有一個參數(shù)很關(guān)鍵視場角。視場角太小垃圾投放口三分之一的區(qū)域在畫面之外視場角太大每件垃圾在畫面里太小小目標(biāo)檢測壓力陡增。我實際用下來80°到100°的水平視場角最合適能在有效檢測距離內(nèi)同時覆蓋投放口和等待區(qū)。還有一個容易被忽略的細節(jié)攝像頭安裝角度。我以前習(xí)慣從正上方俯拍后來發(fā)現(xiàn)斜向下45°視角對人手持垃圾靠近投放口這個動作的魯棒性更好因為正俯拍會被人的手部遮擋。這個調(diào)整不需要改任何代碼但對檢測成功率的提升是立竿見影的。6.2 個人經(jīng)驗總結(jié)與給后來者的建議整套系統(tǒng)從零到穩(wěn)定運行我最大的體會是視覺檢測項目里模型訓(xùn)練只占最后20%的精力前面80%的時間基本都在和數(shù)據(jù)、環(huán)境、硬件打交道。很多剛開始做這個方向的朋友把時間全花在調(diào)整網(wǎng)絡(luò)結(jié)構(gòu)上其實是在錯誤的方向上努力。給你幾個可直接抄的建議先搭通攝像頭到推理到輸出的最小閉環(huán)再回頭優(yōu)化模型精度不要讓前期的完美主義拖住進度。每一類垃圾單獨統(tǒng)計精確率和召回率只看整體準(zhǔn)確率會掩蓋個別類別的嚴(yán)重缺陷。置信度閾值不要只拍腦袋定畫一遍置信度-準(zhǔn)確率曲線在曲線拐點附近選值。所有實驗記錄都寫下來包括數(shù)據(jù)集版本、增強配置、超參、評價指標(biāo)。我復(fù)現(xiàn)不了自己兩周前的最佳結(jié)果時才發(fā)現(xiàn)有個實驗參數(shù)當(dāng)時忘了記。這套系統(tǒng)的下一步我打算在檢測結(jié)果之上疊加一個投放行為的時序判斷根據(jù)目標(biāo)在畫面中的軌跡判斷它是不是被正確投放進了對應(yīng)的桶而不是僅僅被識別出來了。檢測只是眼睛判斷行為才算有了腦子。這個方向做扎實了垃圾分類終端才真正談得上智能兩個字。