優(yōu)實戰(zhàn):小目標(biāo)優(yōu)化與端側(cè)部署策略)
簡介面向智慧工地安全領(lǐng)域的YOLOv11目標(biāo)檢測開發(fā)者《智慧工地安全YOLOv11高空作業(yè)安全帶佩戴檢測模型調(diào)優(yōu)技巧》是一份51頁的PDF文檔。內(nèi)容覆蓋YOLO系列算法原理回顧、高空作業(yè)安全帶數(shù)據(jù)集的采集標(biāo)注與預(yù)處理、學(xué)習(xí)率/批量大小等超參數(shù)調(diào)優(yōu)、數(shù)據(jù)增強策略、訓(xùn)練驗證流程優(yōu)化、常用性能指標(biāo)分析以及云端/邊緣/混合部署案例可為安防監(jiān)控、工業(yè)檢測等場景下快速落地高精度安全帶佩戴檢測方案提供參考。資源包內(nèi)僅包含1個PDF文件壓縮包大小2.26MB文檔無缺頁或亂碼文字、圖表、目錄均顯示正常支持閱讀器大綱與章節(jié)快速定位可按目錄順序閱讀或直接跳轉(zhuǎn)目標(biāo)章節(jié)。目前已有142人學(xué)習(xí)下載適合希望系統(tǒng)掌握YOLOv11模型調(diào)優(yōu)技巧的研究者、算法工程師及相關(guān)專業(yè)學(xué)生查閱使用為實際項目提供可復(fù)用的調(diào)參思路。1. 高空作業(yè)安全帶檢測為什么先聊 YOLOv11 調(diào)優(yōu)而不是換模型在智慧工地項目里安全帶佩戴檢測是最容易被低估的一類視覺任務(wù)。高空場景中安全帶掛點小、工人距離攝像機遠(yuǎn)正樣本往往只占圖像幾十個像素加上逆光、遮擋和反光背心的干擾模型稍有不慎就從高召回跌成高誤報。用 YOLOv11 做這個任務(wù)不是因為它在 COCO 上刷榜而是它的解耦頭、訓(xùn)練收斂特性和端側(cè)部署路徑在工程上最省心——真正決定項目能不能驗收的是后續(xù)的模型調(diào)優(yōu)技巧小目標(biāo)優(yōu)化、數(shù)據(jù)配比、NMS 后處理和量化部署。這篇筆記按我自己在工地項目里的流程來寫從網(wǎng)絡(luò)結(jié)構(gòu)怎么理解到標(biāo)簽怎么標(biāo)、參數(shù)怎么調(diào)、坑在哪、部署怎么省內(nèi)存讀完你可以在自己的數(shù)據(jù)集上直接把參數(shù)抄走試一遍。2. YOLOv11 網(wǎng)絡(luò)結(jié)構(gòu)里跟安全帶檢測直接相關(guān)的部分先理解再動手2.1 從 C3k2 到 SPPF 變體哪些模塊真正影響小目標(biāo)召回YOLOv11 的 backbone 和 neck 相比 YOLOv8 最大的變化是把原來 C2f 里的一部分卷積路徑換成了 C3k2 模塊。C3k2 的核心是用更小的 kernel 組合替代部分大卷積理論上參數(shù)更省但實際上對安全帶這類小目標(biāo)的檢測它并不直接決定召回率。真正決定小目標(biāo)能不能被檢出來的是下采樣倍率和特征層融合的方式。YOLOv11 默認(rèn)還是 P3/P4/P5 三尺度輸出。P3 對應(yīng) 8 倍下采樣是安全帶檢測的主戰(zhàn)場。巡邏球機畫面里一根安全帶的寬度通常在 8~16 像素之間只有落在 P3 層上的特征才有足夠分辨力。如果按默認(rèn)的 640 輸入去訓(xùn)練P3 層感受野大概是 8×8 的原始區(qū)域?qū)φ瞻踩珟繕?biāo)規(guī)模勉強夠用但如果施工現(xiàn)場把攝像機架在塔吊臂或基坑邊緣目標(biāo)縮到 4 像素P3 也救不回來。C3k2 里有一個可以調(diào)的小參數(shù)是中間 bottleneck 的個數(shù)。默認(rèn)配置下C3k2 在 backbone 的每個 stage 里只堆 1 個 bottleneck如果你發(fā)現(xiàn) P3 層小目標(biāo)漏檢多可以把 backbone 前兩個 stage 的 bottleneck 數(shù)加一倍代價是訓(xùn)練速度大約降 15%但對小目標(biāo)的特征表達(dá)能力會有可感知的提升。這個改動不需要改模型結(jié)構(gòu)文件直接在 YOLOv11 的 yaml 配置里改數(shù)字就行。2.2 SPPF 的 pool 尺寸選擇與目標(biāo)尺寸的匹配關(guān)系YOLOv11 的 SPPF 模塊用三個串聯(lián)的 5×5 max pool 來擴大感受野。對于安全帶這類小目標(biāo)SPPF 的 pool 尺寸影響很小但有一個容易翻車的點如果你為了適配工地場景把輸入分辨率從 640 提到 1280但 SPPF 的 pool 尺寸沒動neck 層輸出特征圖變大之后信息聚合范圍相對變小對極小目標(biāo)不一定有幫助。我的做法是當(dāng)輸入分辨率提升到 1280 時把 SPPF 的三個 pool 從 5 改成 3。理由是高空圖像里目標(biāo)雖然小但背景也相對干凈不需要過大的感受野去關(guān)聯(lián)上下文——安全帶就是一條帶子掛在人身上上下文范圍比車輛檢測小得多。改 pool 尺寸在 yaml 里同樣是一行事。# yolov11-safety.yaml 片段基于 yolov11s 調(diào)整 backbone: - [-1, 1, Conv, [64, 3, 2]] - [-1, 1, Conv, [128, 3, 2]] - [-1, 2, C3k2, [256, False]] - [-1, 1, Conv, [256, 3, 2]] - [-1, 2, C3k2, [512, False]] - [-1, 1, Conv, [512, 3, 2]] - [-1, 2, C3k2, [1024, False]] - [-1, 1, SPPF, [1024, 3]] # 原為 51280 輸入時改成 3上面這段 yaml 里SPPF, [1024, 3]最后的數(shù)字 3 就是 pool kernel size。如果你輸入分辨率保持 640不建議動它。這里需要注意改了 SPPF 的 pool 尺寸之后neck 層的通道數(shù)不會變所以預(yù)訓(xùn)練權(quán)重依然可以加載不會出現(xiàn) shape mismatch 的問題。如果你想在 neck 里再接一個注意力模塊HCANet 那種思路可以參考——在 P3 層輸出前加一個通道注意力強制模型關(guān)注安全帶這種細(xì)長結(jié)構(gòu)。不過常見做法是在訓(xùn)練穩(wěn)定之后再加一開始就加會讓收斂變慢損失曲線會長時間下不去。2.3 解耦頭與 loss 分配為什么安全帶檢測容易「檢得出、框不準(zhǔn)」YOLOv11 的 head 是解耦的分類分支和回歸分支各走各的卷積。安全帶的分類很簡單就一個類別難的是回歸——安全帶的框是極端的長條形寬高比常常超過 1:5而默認(rèn) anchor-free 的回歸頭對極端長寬比目標(biāo)天生不敏感。訓(xùn)練時如果發(fā)現(xiàn) mAP50 還可以、mAP50-95 一直低大概率是回歸分支對長條形目標(biāo)的定位精度不足。常見解決路徑有兩個一是把回歸 loss 從默認(rèn)的 CIoU 換成 SIoUSIoU 對角度和長寬比更敏感對細(xì)長目標(biāo)有明顯改善二是在數(shù)據(jù)增強里對長條形目標(biāo)做專門的隨機旋轉(zhuǎn)增強讓模型見過更多角度的安全帶避免它把豎直佩戴的安全帶學(xué)了、斜挎的就漏掉。# 在 YOLOv11 的 loss 配置里切換回歸 loss 的寫法 # ultralytics/cfg/default.yaml 中修改 loss 相關(guān)參數(shù) loss: box: 7.5 # 默認(rèn) 7.5長條形目標(biāo)可提到 9.0 cls: 0.5 # 單類別任務(wù)可以再降 dfl: 1.5 # 分布式 focal loss建議保持默認(rèn)參數(shù)說明box權(quán)重提高之后模型會更賣力地把框回歸準(zhǔn)但如果你的工地畫面里遮擋嚴(yán)重框的標(biāo)注本身就帶噪聲box 權(quán)重太高反而會把標(biāo)注噪聲學(xué)進(jìn)去。cls在單類別任務(wù)里不是瓶頸降一點可以防止分類分支和回歸分支在解耦頭里互相搶梯度。最后說環(huán)境配置。YOLOv11 的訓(xùn)練環(huán)境其實沒有想象中苛刻CUDA 11.8 以上配 PyTorch 2.xultralytics 包直接 pip 裝就行。真正要注意的是 batch size 和顯存的匹配后面第 4 章會細(xì)說。3. 數(shù)據(jù)與標(biāo)簽策略安全帶檢測的成敗在標(biāo)注階段就定了3.1 安全帶目標(biāo)尺寸分布統(tǒng)計小目標(biāo)優(yōu)化的前提很多工地項目的標(biāo)注數(shù)據(jù)是直接找外包標(biāo)了事。做 YOLOv11 小目標(biāo)優(yōu)化前第一步先統(tǒng)計目標(biāo)尺寸分布連目標(biāo)多小都不知道談優(yōu)化就是玄學(xué)。用下面的腳本把標(biāo)注框的尺寸分布拉出來看 P3 層理論上能不能覆蓋。import json from collections import Counter # 假設(shè)標(biāo)注是 labelme 格式這里換成你自己的解析邏輯 with open(annotations.json, r) as f: data json.load(f) size_bins Counter() for img in data[images]: for ann in img[annotations]: w ann[bbox][2] # 標(biāo)注框?qū)?h ann[bbox][3] # 標(biāo)注框高 max_side max(w, h) if max_side 8: size_bins[8px] 1 elif max_side 16: size_bins[8-16px] 1 elif max_side 32: size_bins[16-32px] 1 else: size_bins[32px] 1 print(size_bins)這段代碼的邏輯很簡單把每個標(biāo)注框的長邊分桶長邊小于 8 像素的在 P3 層上都不一定有一個完整的 anchor 特征覆蓋。統(tǒng)計完之后如果8px的比例超過 20%你的調(diào)優(yōu)重心就必須放在輸入分辨率和復(fù)制粘貼增強上而不是去調(diào) NMS 閾值。參數(shù)上需要關(guān)注的是 bbox 坐標(biāo)系的歸一化方式——如果標(biāo)注文件里是像素坐標(biāo)而訓(xùn)練時用的是歸一化坐標(biāo)尺寸分布會被算錯先把單位統(tǒng)一了再統(tǒng)計。3.2 標(biāo)注規(guī)范反光背心、安全繩和安全帶的區(qū)分安全帶檢測最常見的標(biāo)注錯誤是把反光背心當(dāng)成安全帶。工地工人普遍穿反光背心背心上的熒光橫條和反光帶在視覺上跟安全帶高度相似尤其當(dāng)工人背對鏡頭時反光背心的肩帶和腰帶看起來就像沒系安全帶。標(biāo)注規(guī)范里必須明確只標(biāo)注跨過肩部和腰部的獨立織帶不標(biāo)反光背心自帶的裝飾條。標(biāo)注框的貼合度也要定標(biāo)準(zhǔn)。安全帶的幾何形態(tài)是一條窄帶但很多外包標(biāo)注員習(xí)慣性把框拉成正方形導(dǎo)致長寬比信息丟失。對回歸分支來說框的長寬比本身就是特征正方形框會讓模型學(xué)到錯誤的目標(biāo)形狀。我一般要求標(biāo)注框緊貼安全帶的可見部分不延伸到人體輪廓之外寧可框小一點不可框大。如果同一人同時系了安全繩和安全帶兩個目標(biāo)重疊度高標(biāo)注時按遮擋關(guān)系只標(biāo)可見的那個。否則訓(xùn)練時同一個位置出現(xiàn)兩個框模型會被 YOLOv11 的匹配策略搞糊涂——它會把兩個框分配給同一個 anchor 區(qū)域?qū)е?loss 震蕩。3.3 數(shù)據(jù)增強組合小目標(biāo)復(fù)制粘貼比 Mosaic 更穩(wěn)YOLOv11 默認(rèn)開啟 Mosaic、MixUp 和 HSV 擾動。但高空安全帶場景有個特殊問題Mosaic 把四張圖拼在一起后目標(biāo)整體縮小到原來的 1/2 甚至 1/4本來就 8 像素的安全帶會變成 2 像素完全超出可學(xué)習(xí)范圍。我在工地項目里直接關(guān)掉了 Mosaic 在最后 50 個 epoch 的作用ultralytics 里可以將mosaic設(shè)為 0 或按 epoch 衰減改用小目標(biāo)復(fù)制粘貼增強。復(fù)制粘貼增強的思路是把標(biāo)注好的安全帶目標(biāo)從原圖摳出來縮放旋轉(zhuǎn)后貼到另一張圖的空曠區(qū)域比如天空、地面、未施工區(qū)域。這個操作能有效增加小目標(biāo)樣本數(shù)因為安全帶的背景變化不大貼圖造成的域偏移很小。# ultralytics/cfg/default.yaml 關(guān)鍵增強參數(shù)基于 YOLOv11 默認(rèn)改 mosaic: 0.5 # 訓(xùn)練前 60% 的 epoch 保留后半程建議降到 0.1 或關(guān)閉 mixup: 0.1 # 單類別任務(wù) mixup 收益小降下來防震蕩 hsv_h: 0.015 # 色調(diào)擾動保持默認(rèn) hsv_s: 0.7 # 飽和度擾動保持默認(rèn) hsv_v: 0.4 # 明度擾動可以開到 0.5工地逆光多 degrees: 45.0 # 關(guān)鍵參數(shù)安全帶佩戴角度變化大旋轉(zhuǎn)增強必須開 translate: 0.1 scale: 0.3參數(shù)說明degrees: 45.0是安全帶檢測最能出效果的一項增強因為工人彎腰、轉(zhuǎn)身、攀爬時安全帶的視覺角度變化遠(yuǎn)大于普通目標(biāo)。mosaic后半程降下來是為了避免小目標(biāo)被過度縮小。mixup對單類別檢測基本沒有正向收益保留一個很小的值防過擬合就夠了。3.4 驗證集構(gòu)建按視頻抽幀而不是按圖像隨機劃分工地數(shù)據(jù)集通常是從監(jiān)控視頻里抽幀得到的。如果直接把所有幀打亂后隨機劃分訓(xùn)練集和驗證集同一個人的同一段動作會同時出現(xiàn)在兩邊驗證集 mAP 會虛高 5~10 個點部署到現(xiàn)場就現(xiàn)原形。正確做法是按視頻片段劃分把每路攝像頭的連續(xù)時間段作為一個整體一部分時間段進(jìn)訓(xùn)練集另一部分時間段進(jìn)驗證集。驗證集要特別覆蓋三類場景工人背對鏡頭、逆光、夜間補光。這三類是最容易在測試階段翻車的如果驗證集里沒有調(diào)優(yōu)就失去了參照。我自己會在訓(xùn)練集之外單獨留一個「hard set」專門放這些惡劣樣本每個 epoch 結(jié)束用 hard set 算一次 mAP這個值比官方驗證集的 mAP 更能反映現(xiàn)場真實水平。4. 訓(xùn)練調(diào)優(yōu)核心參數(shù)與超參數(shù)組合從 loss 曲線到 mAP 的完整鏈路4.1 輸入分辨率與 batch size 的匹配先算顯存賬YOLOv11 小目標(biāo)優(yōu)化的第一個杠桿是輸入分辨率。默認(rèn) 640 輸入下8 像素的安全帶在 P3 層上只剩 1×1 個特征點幾乎沒有形狀信息。我把輸入分辨率提到 960 或 1280P3 層上 8 像素目標(biāo)能占 2×2 到 3×3 個特征點召回率會有肉眼可見的提升特別是從球機遠(yuǎn)距離畫面里檢出安全帶。但分辨率不是白提的。960 輸入比 640 輸入的計算量大 2.25 倍顯存占用同步上漲。用 4090 24G 訓(xùn)練時batch size 從默認(rèn) 16 要降到 8不然直接 OOM。1280 輸入下我通常會配合梯度累積來模擬更大的 batch。# 960 輸入 梯度累積的啟動命令 yolo train \ datasafety.yaml \ modelyolov11s.pt \ imgsz960 \ batch8 \ epochs150 \ optimizerSGD \ lr00.01 \ lrf0.01 \ warmup_epochs3.0 \ cos_lrTrue \ accumulate4參數(shù)說明accumulate4表示每 4 個 batch 做一次梯度更新等效 batch size 是 32比直接開 batch32 省顯存但訓(xùn)練時間會略長。optimizerSGD是我在小目標(biāo)檢測任務(wù)上的習(xí)慣——AdamW 收斂快但后期容易在小目標(biāo)回歸上震蕩SGD 配合 cosine 學(xué)習(xí)率衰減更穩(wěn)。warmup_epochs3.0不能省YOLOv11 前幾個 epoch 的 anchor 分配還很不穩(wěn)定跳過了容易在第一個 epoch 就損失爆炸。4.2 anchor 分配策略與 loss 權(quán)重三條經(jīng)驗參數(shù)YOLOv11 是 anchor-free 的但它在訓(xùn)練時仍然有正樣本匹配的過程。默認(rèn)的匹配策略會根據(jù)目標(biāo)的寬高比選擇特征層對細(xì)長目標(biāo)不會特別照顧。這里有三條調(diào)參經(jīng)驗第一把boxloss 權(quán)重從默認(rèn) 7.5 提到 9.0 到 10.0。安全帶的分類很簡單模型不會認(rèn)錯難的是框的邊界特別是肩帶和腰帶交叉的位置。第二把cls權(quán)重從默認(rèn) 0.5 降到 0.3。單類別任務(wù)里分類分支的梯度會主導(dǎo)早期訓(xùn)練壓一壓能讓回歸分支拿到更多梯度。第三dfl保持默認(rèn) 1.5 不要動。DFL 對邊界框的離散分布建模很敏感亂調(diào)會讓框收斂到錯誤的位置。# 推薦的安全帶檢測 loss 權(quán)重配置 loss: box: 9.5 # 原 7.5長條形目標(biāo)回歸壓力大 cls: 0.3 # 原 0.5單類別任務(wù)分類壓力小 dfl: 1.5 # 保持默認(rèn)這三種設(shè)置的效果反映在驗證集上通常是 mAP50 變化不大但 mAP50-95 會從 35 左右升到 42 左右。如果你的項目驗收只看 mAP50這一個改動不夠明顯但在實際抓拍里框會從「大概框住人」變成「框住安全帶本體」下游的違規(guī)判定邏輯才寫得下去。4.3 訓(xùn)練輪數(shù)與學(xué)習(xí)率策略從 loss 曲線判斷何時停安全帶檢測數(shù)據(jù)集一般就幾千張訓(xùn)練 150 epoch 足夠。關(guān)鍵是學(xué)會看 loss 曲線而不是盲目加輪數(shù)。YOLOv11 訓(xùn)練時主要看兩條曲線訓(xùn)練 loss 和驗證 mAP。如果訓(xùn)練 loss 還在穩(wěn)定下降、驗證 mAP 也還在漲說明欠擬合繼續(xù)訓(xùn)如果訓(xùn)練 loss 還在降但驗證 mAP 不動了開始過擬合就該回調(diào)增強或提前停止。硬要給出一個可抄的參數(shù)我會建議warmup 3 個 epoch、cosine 學(xué)習(xí)率、初始 lr0 在 SGD 下用 0.01、在 AdamW 下用 0.001。訓(xùn)練到 30 epoch 時如果 mAP50 還沒過 50先別急著調(diào)參回看數(shù)據(jù)質(zhì)量和標(biāo)注規(guī)范——大多數(shù)時候是標(biāo)注問題而不是模型問題。4.4 模型結(jié)構(gòu)選擇yolov11s 是工地場景的性價比底線YOLOv11n 在 Jetson 上跑得最快但從小目標(biāo)檢測的效果看n 模型在 P3 層上的特征通道太少8 像素的安全帶基本學(xué)不出形狀。工地項目我至少用yolov11s如果對精度要求高且部署端是 PC 或云端yolov11m更穩(wěn)。模型越大P3 層能表達(dá)的特征越豐富對極小目標(biāo)的提升是結(jié)構(gòu)性的比調(diào)任何 loss 權(quán)重都直接。模型imgszmAP50自測Jetson 推理耗時顯存占用bs8yolov11n64082.49ms6.2Gyolov11s96089.116ms9.8Gyolov11m128092.331ms15.4G表格里的數(shù)字是項目里接近的量級不同工地場景會差不少但比值有參考性。yolov11s在 960 輸入下mAP50 和推理耗時最平衡是我的默認(rèn)選擇。想上yolov11m先確認(rèn)部署端的算力預(yù)算否則訓(xùn)練出來了也落不了地。4.5 訓(xùn)練產(chǎn)物管理每次實驗保留完整配置與權(quán)重調(diào)優(yōu)過程中最大的坑不是參數(shù)不對而是改亂了不知道哪版參數(shù)跑出哪個結(jié)果。我每個實驗都固定用 ultralytics 的自動日志跑完直接看runs/detect/train/里的args.yaml和weights/best.pt。args.yaml記錄了這次實驗的全部參數(shù)best.pt是按驗證集 mAP 保存的最優(yōu)權(quán)重。如果要管理多個實驗版本給每次訓(xùn)練命名加后綴yolo train modelyolov11s.pt datasafety.yaml imgsz960 batch8 epochs150 nameexp_s_960_v2nameexp_s_960_v2會讓訓(xùn)練輸出到runs/detect/exp_s_960_v2/目錄不會覆蓋之前的實驗。到了調(diào)優(yōu)后期你會發(fā)現(xiàn)最值錢的就是這份實驗記錄——回滾的時候它就是后悔藥。5. 模型調(diào)優(yōu)避坑指南5 個反復(fù)出現(xiàn)的現(xiàn)場問題5.1 遠(yuǎn)距離小目標(biāo)漏檢P3 層單獨加權(quán)現(xiàn)象驗證集上一切正常一到現(xiàn)場球機畫面距離超過 15 米的工人就檢不出來。原因現(xiàn)場距離導(dǎo)致目標(biāo)實際像素比訓(xùn)練集里的分布更小。訓(xùn)練集的標(biāo)注框長邊中位數(shù)是 14 像素現(xiàn)場遠(yuǎn)距離目標(biāo)只有 5~7 像素超出了訓(xùn)練分布的下界。解決不用換網(wǎng)絡(luò)先做兩件事。第一把訓(xùn)練集里小于 8 像素的目標(biāo)做 2~3 倍復(fù)制粘貼增強強制把訓(xùn)練分布往下擴第二推理時把輸入分辨率從 960 提到 1120。ultralytics 支持在 predict 時設(shè)置imgsz跟訓(xùn)練時不一致也沒關(guān)系。經(jīng)過這兩個改動后現(xiàn)場遠(yuǎn)距離召回能從 50 提到 70 左右。5.2 逆光場景誤檢嚴(yán)重不做額外處理先看訓(xùn)練增強現(xiàn)象下午低角度陽光時把安全繩的陰影誤檢成安全帶或者把塔吊鋼絲繩誤檢成目標(biāo)誤報率飆升。原因安全帶的 HSV 特征在逆光下發(fā)生偏移模型學(xué)到的顏色分布和形狀特征在強陰影下失效。解決把hsv_v從默認(rèn) 0.4 開到 0.6hsv_s從 0.7 開到 0.9在訓(xùn)練階段就見過更寬的亮度變化。另外不要在輸入圖像上額外加自適應(yīng)直方圖均衡工地畫面的亮度分布很復(fù)雜全局均衡反而會把陰影加重。5.3 NMS 把密集人群中的多個目標(biāo)壓成一個框現(xiàn)象腳手架上有兩三個人同時作業(yè)距離很近模型檢出了多個安全帶但 NMS 之后只保留了一個框或直接框住兩個人。原因YOLOv11 默認(rèn) NMS 閾值是 0.5對密集重疊目標(biāo)來說太激進(jìn)重疊度高的小目標(biāo)會被吞掉。解決把 NMS 的 IoU 閾值從 0.5 降到 0.3 到 0.35。在 ultralytics 里推理時可以設(shè)置iou0.35。代價是密集場景下的重復(fù)框會多一些需要在后處理里按置信度排序去重。# 推理時降低 NMS IoU 閾值保留密集小目標(biāo) from ultralytics import YOLO model YOLO(runs/detect/exp_s_960_v2/weights/best.pt) results model.predict( sourcecamera_008.mp4, imgsz1120, conf0.35, # 置信度閾值按需調(diào)整 iou0.35, # NMS IoU 閾值密集場景調(diào)低 saveTrue, )參數(shù)說明conf0.35和iou0.35是兩個不同維度——conf控制哪些框被保留iou控制重疊框怎么合并。如果你降低iou之后重復(fù)框變多說明conf可以適當(dāng)提高一點。yolov11 保存推理結(jié)果時saveTrue會自動把標(biāo)注框畫在幀上并保存為視頻或圖片這個參數(shù)在排查階段很好用——直接看可視化結(jié)果就能判斷是 NMS 的問題還是檢測器的問題。5.4 驗證集 mAP 高、現(xiàn)場表現(xiàn)差數(shù)據(jù)泄漏與場景偏差現(xiàn)象訓(xùn)練時驗證集 mAP50 到了 92一到現(xiàn)場只有 70 不到差距大到無法解釋。原因兩類問題疊加。第一驗證集按幀隨機劃分同一段視頻的相似幀同時進(jìn)了訓(xùn)練集和驗證集mAP 虛高。第二現(xiàn)場攝像機安裝角度和訓(xùn)練數(shù)據(jù)差異大球機的俯視視角在訓(xùn)練集里占比太少。解決驗證集按視頻片段而不是按幀劃分施工前先建一個 hard set。安裝新的攝像機后先用它錄 30 分鐘素材人工標(biāo)注后做一次增量微調(diào)。這類問題沒有一勞永逸的解法只能在數(shù)據(jù)閉環(huán)上做文章。5.5 Jetson Nano 上訓(xùn)練好的模型推理時內(nèi)存溢出現(xiàn)象PC 上跑得好好的 best.pt轉(zhuǎn)到 Jetson Nano 上推理前幾幀正常幾分鐘后進(jìn)程被殺報 out of memory。原因PyTorch 模型在 Jetson 上直接跑推理時會有大量顯存碎片視頻流讀寫沒釋放句柄每幀都做圖像縮放對象內(nèi)存只增不減。解決先轉(zhuǎn) TensorRT 再部署這會同時解決速度和內(nèi)存問題。Jetson Nano 的詳細(xì)部署步驟見第 6 章這里只說關(guān)鍵點視頻幀要復(fù)用同一個 cv2.VideoWriter 對象不要每幀新建幀處理完馬上釋放推理統(tǒng)一走 TensorRT engine不再加載 PyTorch 模型。6. 從 PyTorch 到 JetsonYOLOv11 安全帶的端側(cè)部署調(diào)優(yōu)實戰(zhàn)端側(cè)部署是智慧工地項目里避不開的環(huán)節(jié)。邊緣盒子和 Jetson 設(shè)備是主流方案這里給一套我常用的 YOLOv11 部署流程從導(dǎo)出到推理都覆蓋重點說yolov11 預(yù)測后保存和 int8 量化的坑。第一步把訓(xùn)練好的 best.pt 導(dǎo)出為 ONNX再轉(zhuǎn) TensorRT。這里注意導(dǎo)出時務(wù)必指定opset12否則 Jetson 上的 TensorRT 版本可能不認(rèn)。第二步用trtexec生成 engine 文件。Jetson Nano 的算力有限建議 FP16 精度int8 需要校準(zhǔn)集且 mAP 下降明顯安全帶這種小目標(biāo)對量化誤差很敏感我不推薦。# 在 Jetson Nano 上導(dǎo)出 ONNX如果直接導(dǎo)出 TensorRT 則跳過這步 yolo export modelbest.pt formatonnx opset12 dynamicFalse imgsz960 # 用 trtexec 生成 FP16 engine trtexec \ --onnxbest.onnx \ --saveEnginebest_fp16.engine \ --fp16 \ --workspace1024參數(shù)說明imgsz960要與訓(xùn)練時的輸入一致或按現(xiàn)場需求重新定——這個參數(shù)決定了推理網(wǎng)絡(luò)輸入張量的尺寸改大之后推理變慢改小之后小目標(biāo)失效。dynamicFalse固定輸入尺寸Jetson 上省顯存也省推理時間。workspace1024是 TensorRT 構(gòu)建時的最大顯存預(yù)算單位是 MB不算太大避免在構(gòu)建階段就爆顯存。構(gòu)建好的 engine 文件可以直接在 Python 里用 TensorRT 加載推理。正規(guī)工程做法是把 engine 的輸入輸出綁定好圖像預(yù)處理用 CUDA 完成幀循環(huán)里只做推理和畫框。import cv2 import numpy as np import tensorrt as trt import pycuda.autoinit # 依賴 pycuda # 加載 engine with open(best_fp16.engine, rb) as f: engine_data f.read() runtime trt.Runtime(trt.Logger(trt.Logger.WARNING)) engine runtime.deserialize_cuda_engine(engine_data) # 推理時輸入圖像尺寸按 engine 定義 input_shape (960, 960) cap cv2.VideoCapture(rtsp://192.168.1.64/live) writer cv2.VideoWriter( output_result.avi, cv2.VideoWriter_fourcc(*XVID), 25, (1920, 1080), ) while True: ret, frame cap.read() if not ret: break # 預(yù)處理resize 到 960歸一化 img cv2.resize(frame, input_shape) img img.astype(np.float32) / 255.0 img img.transpose(2, 0, 1)[None] # 推理 后處理省略 TensorRT 綁定細(xì)節(jié) # boxes, scores infer(engine, img) # 畫框并保存 writer.write(frame) cap.release() writer.release()邏輯說明這個幀循環(huán)是最小可用的骨架。yolov11 推理結(jié)果保存的正確做法是復(fù)用同一個 VideoWriter而不是每幀調(diào)用 imwrite——工地視頻一跑就是幾十分鐘頻繁磁盤 IO 會掉幀甚至卡死。writer的編碼用 XVID兼容性比 MJPG 穩(wěn)文件大小也控制得住。如果你的工地攝像頭是槍機固定機位還有一個內(nèi)存優(yōu)化技巧畫面里的施工區(qū)域只占一部分可以先把檢測區(qū)域裁剪出來再做 resize。這樣輸入尺寸可以從 960 降到 640Jetson 上的推理延遲能從 40ms 降到 18ms 左右漏檢率也不會明顯變差——因為被裁掉的區(qū)域本來就沒有作業(yè)面。最后說一個我長期以來的操作習(xí)慣任何部署項目第一次跑通都先保存一份帶檢測框的輸出視頻而不是只看終端日志里的檢測數(shù)量。檢測數(shù)量可以騙人但框在畫面上畫沒畫正、有沒有飄一眼就能看出來。這個習(xí)慣幫我避過無數(shù)次「模型指標(biāo)正常但現(xiàn)場不可用」的翻車。希望這些調(diào)優(yōu)技巧能幫你在工地上少踩幾個坑。本文還有配套的精品資源點擊獲取