數(shù)實(shí)戰(zhàn):從訓(xùn)練到邊緣部署)
簡介一份面向農(nóng)業(yè)智能化與計(jì)算機(jī)視覺開發(fā)者的實(shí)戰(zhàn)型PDF技術(shù)文檔系統(tǒng)講解如何基于YOLOv11與多光譜圖像處理完成農(nóng)業(yè)病蟲害檢測(cè)系統(tǒng)的開發(fā)。YOLOv11憑借單階段檢測(cè)特性兼顧速度與精度使系統(tǒng)在實(shí)時(shí)監(jiān)測(cè)場(chǎng)景中具備明顯優(yōu)勢(shì)。文檔針對(duì)傳統(tǒng)人工檢測(cè)效率低、結(jié)果主觀性強(qiáng)、難以實(shí)時(shí)監(jiān)測(cè)等農(nóng)業(yè)痛點(diǎn)以葉片分割與蟲害計(jì)數(shù)兩大任務(wù)為主線覆蓋多光譜數(shù)據(jù)采集與預(yù)處理、YOLOv11基礎(chǔ)理論、葉片分割算法實(shí)現(xiàn)、蟲害計(jì)數(shù)方法設(shè)計(jì)、系統(tǒng)開發(fā)與集成、實(shí)驗(yàn)結(jié)果分析與典型應(yīng)用場(chǎng)景等完整技術(shù)鏈路并涵蓋數(shù)據(jù)增強(qiáng)、模型融合與評(píng)估指標(biāo)等細(xì)節(jié)幫助讀者建立從算法到工程落地的認(rèn)知適合算法工程師、農(nóng)業(yè)科研人員及高校學(xué)生按目錄快速查閱。資源為PDF格式共1個(gè)文件壓縮包大小約2.02MB文檔共40頁文字、圖表、目錄顯示完整支持大綱跳轉(zhuǎn)和章節(jié)定位目前已有101人瀏覽學(xué)習(xí)可作為農(nóng)業(yè)病蟲害檢測(cè)項(xiàng)目入門參考。1. 農(nóng)業(yè)病蟲害檢測(cè)的硬骨頭為什么是YOLOv11多光譜田間拍回來的照片要么背景全是土和雜草要么葉片被陰影壓成一片死黑。做病蟲害檢測(cè)的同行都有體會(huì)用普通RGB圖訓(xùn)練出來的分割模型換個(gè)地塊、換套光照就崩蟲體小到只有十幾個(gè)像素?cái)?shù)都數(shù)不清。農(nóng)業(yè)病蟲害檢測(cè)實(shí)戰(zhàn)里把多光譜信息和YOLOv11的實(shí)例分割能力結(jié)合起來走“多光譜葉片分割蟲害計(jì)數(shù)”這條路是這幾年我們驗(yàn)證下來最穩(wěn)的方向。多光譜能把健康葉片和病斑從光譜上分開YOLOv11的分割頭負(fù)責(zé)把葉片輪廓摳出來計(jì)數(shù)交給掩膜分析而不是靠數(shù)框框。這套方法適合正在做植保信息化、智能蟲情測(cè)報(bào)或者想用視覺模型替代人工田間調(diào)查的團(tuán)隊(duì)。讀完這篇你能拿到一條從數(shù)據(jù)采集、模型訓(xùn)練、計(jì)數(shù)統(tǒng)計(jì)到邊緣設(shè)備部署的完整落地路徑。2. 多光譜數(shù)據(jù)從哪來波段選擇、采集設(shè)備與標(biāo)注規(guī)范2.1 多光譜和RGB的區(qū)別五個(gè)波段還是越寬越好多光譜不是玄學(xué)它的核心價(jià)值在于把“顏色”擴(kuò)展成“光譜響應(yīng)曲線”。普通RGB相機(jī)把400到700nm可見光壓縮成三個(gè)通道而多光譜傳感器在同樣的視場(chǎng)里多采了幾個(gè)窄帶波段。水稻稻瘟病、小麥條銹病這類病害發(fā)病初期葉片在RGB圖里只是微微發(fā)黃人眼很難判斷但紅邊波段700到750nm和近紅外波段750到900nm的反射率變化非常明顯。這也是為什么植保方向的公開數(shù)據(jù)集大多帶RedEdge和NIR通道。選波段的時(shí)候一個(gè)常見誤區(qū)是“波段越多越好”。我做過的方案里用的是典型植保無人機(jī)多光譜相機(jī)的五通道配置藍(lán)450nm中心波長、綠560nm、紅650nm、紅邊730nm、近紅外840nm。為什么不直接上十幾個(gè)波段的高光譜數(shù)據(jù)量、標(biāo)定成本和模型復(fù)雜度都會(huì)失控而且YOLOv11的輸入端按通道數(shù)接受圖像通道太多會(huì)把訓(xùn)練時(shí)間拖垮。五個(gè)波段里藍(lán)綠紅合成RGB圖喂給模型做外觀特征紅邊和近紅外作為額外通道參與植被指數(shù)計(jì)算這個(gè)組合在絕大多數(shù)田間場(chǎng)景下已經(jīng)夠用。通道中心波長典型半高寬在葉片分割里的用途Blue450nm35nm合成RGB基礎(chǔ)通道提供紋理細(xì)節(jié)Green560nm40nm正常葉綠素反射峰區(qū)分活體葉片Red650nm40nm葉綠素吸收帶病斑區(qū)反射率偏高RedEdge730nm40nm病害早期敏感波段紅邊位移檢測(cè)NIR840nm50nm葉片含水量與細(xì)胞結(jié)構(gòu)區(qū)分枯葉與背景多光譜數(shù)據(jù)的采集方式有兩種無人機(jī)搭載多光譜相機(jī)飛正射或者地面手持多光譜相機(jī)貼近葉片拍。無人機(jī)適合田塊級(jí)蟲情普查地面拍攝適合葉片級(jí)分割和蟲害細(xì)粒度計(jì)數(shù)后者和“葉片分割”這個(gè)目標(biāo)更匹配。采集時(shí)有個(gè)硬性要求多光譜相機(jī)的光照傳感器必須直視天空每次起飛前做一次白板校準(zhǔn)否則太陽高度角變化會(huì)讓各波段反射率失去可比性。把這種校準(zhǔn)視為拍照流程的一部分不要指望軟件后處理能完全救回來。2.2 葉片分割的標(biāo)注規(guī)范掩膜格式與類目設(shè)計(jì)多光譜數(shù)據(jù)拿到手之后要先做預(yù)處理才能進(jìn)入訓(xùn)練管線。常見做法是把原始五通道TIFF拆成單波段藍(lán)綠紅合成為RGB圖紅邊和近紅外分別存為兩個(gè)單通道灰度圖然后五通道直接拼成一個(gè)5通道Tensor送入YOLOv11。有人會(huì)把RGB、紅邊、近紅外做成三圖并列的多流輸入也有人把紅邊NIR合成偽彩色圖工程上最穩(wěn)妥的還是直接拼通道YOLOv11的輸入層改一個(gè)參數(shù)就能接住。標(biāo)注規(guī)范是這套方案能不能復(fù)現(xiàn)的關(guān)鍵。葉片分割的標(biāo)注用COCO的polygon格式一個(gè)葉片一個(gè)實(shí)例病斑區(qū)域單獨(dú)標(biāo)一個(gè)類不要混在葉片輪廓里。類目設(shè)計(jì)上至少分四類正常葉片、病斑葉片、蟲害葉片、背景?!跋x害葉片”和“病斑葉片”的差別在于蟲害葉片通常有咬噬邊緣或蟲糞附著分割模型需要靠紋理細(xì)節(jié)區(qū)分。標(biāo)注時(shí)要放大到單個(gè)葉片占畫面至少30%再勾輪廓否則小面積類的邊緣會(huì)被標(biāo)注員隨手畫成多邊形訓(xùn)練完掩膜邊界全是鋸齒。{ info: { description: multispectral leaf segmentation dataset, channels: 5, width: 1280, height: 960 }, categories: [ {id: 0, name: normal_leaf, supercategory: leaf}, {id: 1, name: diseased_leaf, supercategory: leaf}, {id: 2, name: pest_leaf, supercategory: leaf}, {id: 3, name: background, supercategory: background} ], annotations: [ { id: 1, image_id: 1, category_id: 1, segmentation: [[310, 210, 315, 260, 355, 250, 360, 205]], area: 2670.5 } ] }上面這個(gè)JSON是COCO格式標(biāo)注的最小骨架。segmentation字段是polygon坐標(biāo)點(diǎn)按先x后y排列閉合點(diǎn)不重復(fù)。標(biāo)注完成后要統(tǒng)計(jì)類別平衡度田間數(shù)據(jù)非常容易出現(xiàn)正常葉片占80%、蟲害葉片只有5%的長尾分布這時(shí)不要急著訓(xùn)練先用基于類別的加權(quán)裁剪增強(qiáng)把少數(shù)類的小圖在每輪隨機(jī)多采樣幾次。這一步不做好模型會(huì)乖乖把所有葉片全預(yù)測(cè)成正常葉片。2.3 從5通道TIFF到Y(jié)OLOv11能吃的輸入預(yù)處理三步走多光譜相機(jī)導(dǎo)出的一般是16位TIFFYOLOv11默認(rèn)接3通道8位圖直接硬喂會(huì)出問題。第一步做輻射定標(biāo)把DN值乘以相機(jī)出廠標(biāo)定系數(shù)轉(zhuǎn)成反射率第二步做波段拉伸把五個(gè)波段分別截取2%到98%的直方圖分位點(diǎn)線性映射到0到255。這里有個(gè)我踩過的坑如果五個(gè)波段各自獨(dú)立拉伸會(huì)破壞波段間的相對(duì)亮度關(guān)系紅邊和近紅外的數(shù)值域會(huì)被拉跑。正確做法是先按NIR波段的統(tǒng)計(jì)量算出一個(gè)全局映射再把這個(gè)映射套用到所有波段。import cv2 import numpy as np from glob import glob # 5波段TIFF讀取和全局拉伸 def load_and_stretch(tiff_path, percent2): img cv2.imread(tiff_path, cv2.IMREAD_UNCHANGED) # 16位 bands np.split(img, 5, axis-1) # 假設(shè)TIFF按波段存儲(chǔ) # 以NIR波段為基準(zhǔn)計(jì)算全局分位數(shù) nir bands[4].astype(np.float32) low np.percentile(nir, percent) high np.percentile(nir, 100 - percent) stretched [] for b in bands: b np.clip((b.astype(np.float32) - low) / (high - low), 0, 1) stretched.append((b * 255).astype(np.uint8)) return np.concatenate(stretched, axis-1) # H, W, 5 data load_and_stretch(field_001.tiff) print(data.shape, data.dtype) # (960, 1280, 5) uint8這段代碼的要點(diǎn)在全局拉伸。percent取2意味著用2%到98%的分位數(shù)壓制極端反光點(diǎn)反光葉片上的鏡面反射不會(huì)把動(dòng)態(tài)范圍全部吃掉。最終輸出的5通道數(shù)組前3通道是RGB后2通道是RedEdge和NIR。訓(xùn)練增強(qiáng)上要注意不要給多光譜通道做RandomBrightnessContrast波段間的比例關(guān)系太敏感我只用幾何增強(qiáng)旋轉(zhuǎn)、翻轉(zhuǎn)、隨機(jī)縮放0.8到1.2倍。顏色類增強(qiáng)只對(duì)RGB部分做輕微HSV擾動(dòng)RedEdge和NIR不參與。3. 跑通YOLOv11葉片分割網(wǎng)絡(luò)結(jié)構(gòu)、環(huán)境配置和訓(xùn)練命令3.1 為什么選YOLOv11的分割頭網(wǎng)絡(luò)結(jié)構(gòu)里藏著對(duì)田間數(shù)據(jù)的妥協(xié)YOLOv11延續(xù)了Ultralytics系列anchor-free的設(shè)計(jì)分割分支和檢測(cè)分支共用主干和頸部只在Head尾部多出一條輸出掩膜的卷積路徑。它用C3k2模塊替代了早期版本的C3模塊在保持感受野的同時(shí)把計(jì)算量降下來PSA注意力機(jī)制放在深層Stage能提升分割任務(wù)對(duì)細(xì)小病斑的敏感度。這些結(jié)構(gòu)上的改進(jìn)帶來的直接結(jié)果是在同樣精度下模型體積更小在NVIDIA Jetson這類邊緣設(shè)備上能把推理幀率提上去這一點(diǎn)對(duì)田間部署很重要。YOLOv11官方給出的分割模型從yolo11n-seg到y(tǒng)olo11x-seg參數(shù)覆蓋從幾MB到上百M(fèi)B。農(nóng)業(yè)現(xiàn)場(chǎng)我一般選yolo11n-seg作為起點(diǎn)做快速驗(yàn)證等確認(rèn)數(shù)據(jù)沒問題之后再用yolo11m-seg提精度。不要一上來就上最大的x版本多光譜五通道輸入本身就把參數(shù)量放大了x版本在Jetson Nano上跑不動(dòng)最后還得回頭壓縮。# 激活虛擬環(huán)境并安裝ultralytics conda create -n agri-yolov11 python3.10 -y conda activate agri-yolov11 pip install ultralytics torch torchvision --index-url https://download.pytorch.org/whl/cu118安裝時(shí)有兩個(gè)注意點(diǎn)。一是Python版本別選3.12某些多光譜圖像處理庫的C擴(kuò)展還沒適配二是PyTorch和CUDA版本要看推理設(shè)備如果在Jetson上跑主機(jī)裝CUDA 11.8版本設(shè)備端用JetPack自帶的PyTorch兩邊版本不要強(qiáng)行統(tǒng)一。裝完后用yolo predict modelyolo11n-seg.pt sourcebush.jpg跑一次自帶權(quán)重確認(rèn)推理鏈路通。3.2 最小訓(xùn)練命令改三個(gè)參數(shù)讓模型接受5通道輸入要讓YOLOv11接受多光譜輸入需要?jiǎng)觾蓚€(gè)地方模型配置里把ch從3改成5數(shù)據(jù)集配置里把nc改成4。常見的做法是直接改yaml文件不推薦在訓(xùn)練腳本里動(dòng)態(tài)改模型通道數(shù)那樣可復(fù)現(xiàn)性差。# leaf_seg.yaml path: /data/multispectral_leaf train: images/train val: images/val nc: 4 names: 0: normal_leaf 1: diseased_leaf 2: pest_leaf 3: background# yolo11n-seg-multispectral.yaml # 基于官方y(tǒng)olo11n-seg.yaml修改只改ch nc: 4 ch: 5 scales: # 模型縮放系數(shù) n: [0.50, 0.25, 1024]# 開始訓(xùn)練 yolo train \ modelyolo11n-seg-multispectral.yaml \ dataleaf_seg.yaml \ epochs200 \ imgsz640 \ batch8 \ workers4 \ device0 \ optimizerSGD \ lr00.01 \ cacheram這段訓(xùn)練命令用SGD而不是默認(rèn)的AdamW原因是多光譜數(shù)據(jù)標(biāo)注成本高、數(shù)據(jù)量普遍偏小SGD配合warmup能收斂到更平滑的極小值測(cè)試集mAP一般比AdamW高1到2個(gè)點(diǎn)。batch設(shè)為8是因?yàn)?通道輸入顯存占用比同樣尺寸的RGB大不少12GB顯存卡上用8比較穩(wěn)。cacheram把整個(gè)數(shù)據(jù)集加載進(jìn)內(nèi)存多光譜數(shù)據(jù)讀取比RGB慢不做這個(gè)訓(xùn)練時(shí)會(huì)頻繁等磁盤IO。imgsz先用640把流程跑通后續(xù)小目標(biāo)優(yōu)化再提1024。訓(xùn)練時(shí)打開兩個(gè)觀察指標(biāo)mask_mAP0.5和mask_mAP0.5:0.95前者看分割輪廓的整體準(zhǔn)確性后者看掩膜邊界貼合度。田間葉片分割的驗(yàn)收底線一般是mAP0.5達(dá)到0.8以上、mAP0.5:0.95達(dá)到0.5以上達(dá)不到就先檢查標(biāo)注質(zhì)量而不是盲目加訓(xùn)練輪數(shù)。3.3 小目標(biāo)優(yōu)化蟲體只有十幾個(gè)像素時(shí)模型為什么漏檢蟲害計(jì)數(shù)場(chǎng)景里蚜蟲、薊馬這類小型害蟲在640尺寸圖像里只有十幾個(gè)像素YOLOv11的默認(rèn)檢測(cè)頭在最深層輸出特征圖下采樣32倍后這些小目標(biāo)幾乎消失。社區(qū)里常用的解法有三個(gè)按見效速度排序切圖推理、增加P2檢測(cè)層、提高輸入分辨率三個(gè)可以疊加用。切圖推理是成本最低的優(yōu)化。把1024尺寸的輸入切成四張512的小圖分別推理再把結(jié)果映射回原圖坐標(biāo)小目標(biāo)相當(dāng)于被放大了一倍。代價(jià)是推理時(shí)間翻四倍但對(duì)課題組聯(lián)排分析離線圖片來說完全值得。增加P2層要改模型結(jié)構(gòu)在neck部分把第2層輸出接入檢測(cè)頭YOLOv11的yaml文件里加一層C2PSA和對(duì)應(yīng)輸出節(jié)點(diǎn)這部分官方文檔沒有現(xiàn)成模板改起來需要看模型參數(shù)量變化來調(diào)寬度系數(shù)。# 提高分辨率重新訓(xùn)練通常比改結(jié)構(gòu)收益更直接 yolo train \ modelleaf_seg_last.pt \ dataleaf_seg.yaml \ epochs50 \ imgsz1024 \ batch4 \ device0 \ resumeFalseimgsz從640提到1024的收益在蟲害計(jì)數(shù)場(chǎng)景非常明顯標(biāo)注里的密集小蟲目標(biāo)會(huì)被激活更多anchor位置。注意batch要相應(yīng)減半顯存不足時(shí)先把workers降到2。實(shí)測(cè)經(jīng)驗(yàn)是640到1024能讓小目標(biāo)的recall提升約10個(gè)百分點(diǎn)代價(jià)是單張推理時(shí)間增加但離線分析場(chǎng)景幾乎不在乎。換到實(shí)時(shí)測(cè)報(bào)場(chǎng)景時(shí)再考慮用切圖推理和TensorRT壓縮拉回幀率。4. 蟲害計(jì)數(shù)不靠數(shù)框從分割掩膜到密度統(tǒng)計(jì)的完整管線4.1 為什么不用檢測(cè)框數(shù)數(shù)重疊蟲體會(huì)把計(jì)數(shù)變成玄學(xué)有段時(shí)間我直接用檢測(cè)分支的box數(shù)量當(dāng)蟲口數(shù)結(jié)果一塌糊涂。蚜蟲密集聚集時(shí)幾十只蟲擠在一片葉子背面檢測(cè)框互相重疊NMS之后只剩幾個(gè)框。換成分割掩膜之后每個(gè)蟲體是一個(gè)獨(dú)立的連通域即使蟲體之間有輕微粘連也能通過輪廓分析拆開。這就是“葉片分割蟲害計(jì)數(shù)”這個(gè)組合的底層邏輯分割模型負(fù)責(zé)把蟲體從葉片背景中分離出來計(jì)數(shù)交給二值圖像分析不再依賴檢測(cè)框。import cv2 import numpy as np def count_pests(mask, min_area8, max_area800): # mask: 模型輸出的二值掩膜背景為0蟲體為255 mask_u8 (mask.squeeze() * 255).astype(np.uint8) # 形態(tài)學(xué)開運(yùn)算去掉單像素噪點(diǎn) kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) cleaned cv2.morphologyEx(mask_u8, cv2.MORPH_OPEN, kernel) # 連通域分析 num, labels, stats, centroids cv2.connectedComponentsWithStats(cleaned, connectivity8) valid_count 0 valid_areas [] for i in range(1, num): area stats[i, cv2.CC_STAT_AREA] if min_area area max_area: valid_count 1 valid_areas.append(area) return valid_count, np.array(valid_areas), centroids[1:][valid_areas] # 假設(shè)pest_mask來自模型輸出的分割掩膜 count, areas, cents count_pests(pest_mask) print(f檢出的蟲口數(shù): {count}, 平均面積: {areas.mean():.1f} px)這段計(jì)數(shù)代碼有三個(gè)關(guān)鍵參數(shù)。min_area8用于過濾分割噪聲點(diǎn)多光譜紅邊通道有時(shí)會(huì)把土壤顆粒誤分為蟲體小于8像素的噪點(diǎn)直接丟掉max_area800用于排除粘連成片的蟲團(tuán)如果葉片背面蟲害密集成片這個(gè)閾值要放寬后配合分水嶺做區(qū)域拆分。連通域用8鄰域而不用4鄰域因?yàn)?鄰域容易把細(xì)長的蟲腿斷開導(dǎo)致一只蟲被數(shù)成兩只。面積和重心的輸出可以用來計(jì)算蟲體大小分布蚜蟲和葉蟬的體積差異能輔助區(qū)分種群。4.2 把計(jì)數(shù)結(jié)果寫回推理結(jié)果保存帶統(tǒng)計(jì)的JSON和可視化YOLOv11的推理結(jié)果默認(rèn)只保存標(biāo)注圖但田間調(diào)查需要的是能直接導(dǎo)入統(tǒng)計(jì)分析軟件的數(shù)據(jù)。常見做法是把每個(gè)葉片的病斑面積、蟲口數(shù)、蟲體平均面積按葉片實(shí)例聚合輸出成JSON。用Ultralytics的Results對(duì)象直接取masks屬性做坐標(biāo)偏移映射后再跑連通域統(tǒng)計(jì)。from ultralytics import YOLO model YOLO(best.pt) results model.predict( sourcetest_field/, imgsz1024, conf0.35, saveTrue, save_txtTrue, projectruns/pest_count, nameexp1 ) summary [] for res in results: masks res.masks.data.cpu().numpy() # 每個(gè)實(shí)例一個(gè)掩膜 class_ids res.boxes.cls.cpu().numpy().astype(int) names res.names for i, mask in enumerate(masks): cls_id class_ids[i] if names[cls_id] ! pest_leaf: continue # 提取該實(shí)例在整圖坐標(biāo)系里的掩膜塊 binary mask 0.5 pest_count, areas, cents count_pests(binary.astype(np.uint8)) summary.append({ image: res.path.split(/)[-1], leaf_area_px: int(binary.sum()), pest_count: int(pest_count), pest_avg_area_px: float(areas.mean()) if len(areas) else 0, }) import json with open(runs/pest_count/summary.json, w) as f: json.dump(summary, f, indent2)predict參數(shù)里conf0.35要重點(diǎn)說明。分割模型的mask置信度偏低默認(rèn)0.25在密集蟲害場(chǎng)景會(huì)混入大量背景噪聲0.5又容易把邊緣模糊的小蟲整塊濾掉我調(diào)試下來0.3到0.4之間最穩(wěn)具體數(shù)值要按驗(yàn)證集調(diào)。saveTrue保存可視化結(jié)果save_txtTrue會(huì)把每個(gè)實(shí)例的歸一化坐標(biāo)存為txt這兩個(gè)參數(shù)是排查模型輸出時(shí)最常用的對(duì)照材料。如果要把計(jì)數(shù)結(jié)果繪制到原圖上用Results對(duì)象的plot()方法就能拿到帶掩膜的圖像再用cv2.putText把蟲口數(shù)寫到圖片左上角。這個(gè)可視化版本不是給人看的是給資方和植保專家看的他們需要一眼確認(rèn)“數(shù)出來的蟲和圖上標(biāo)的位置對(duì)得上”。4.3 驗(yàn)證計(jì)數(shù)精度不要只看mAP用人工計(jì)數(shù)對(duì)比模型分割mAP再高也不等于蟲口數(shù)準(zhǔn)確。我吃過這個(gè)虧掩膜mAP到了0.85人工復(fù)核時(shí)發(fā)現(xiàn)模型把葉片背面的蟲糞顆粒當(dāng)成了蟲體計(jì)數(shù)虛高。正確做法是專門建一個(gè)計(jì)數(shù)驗(yàn)證集每張圖拍完后人工數(shù)一遍和模型輸出做對(duì)比用平均絕對(duì)百分比誤差MAPE和決定系數(shù)R2兩個(gè)指標(biāo)評(píng)判。之前交付的蟲情測(cè)報(bào)系統(tǒng)里驗(yàn)證標(biāo)準(zhǔn)是MAPE低于15%才算驗(yàn)收通過達(dá)不到就回去調(diào)min_area閾值最差情況才考慮換更大的模型。計(jì)數(shù)驗(yàn)證還需要?jiǎng)澇觥盎煜齾^(qū)間”。人工數(shù)10只以下和人工數(shù)200只以上的圖模型誤差形態(tài)完全不同低密度主要錯(cuò)在漏檢高密度主要錯(cuò)在粘連。優(yōu)化時(shí)不要只用全量MAPE分密度段去看誤差來源低密度段提升分辨率高密度段改善分割邊界的收縮程度。這兩個(gè)方向的改動(dòng)是不同的混在一起調(diào)參容易兩頭不討好。5. 常見問題與避坑記錄五通道數(shù)據(jù)訓(xùn)練與部署的五個(gè)坑5.1 多光譜通道全堆進(jìn)去精度反而比純RGB更差現(xiàn)象把五個(gè)通道直接拼起來訓(xùn)練了一個(gè)百輪模型驗(yàn)證集mAP只有0.62回到純RGB三通道重新訓(xùn)練同樣數(shù)據(jù)mAP反而到了0.70。這看起來違反直覺多光譜信息明明是增強(qiáng)怎么成了負(fù)優(yōu)化。原因訓(xùn)練數(shù)據(jù)量不足時(shí)五個(gè)通道的參數(shù)量把模型自由度過分放大紅邊和近紅外通道的標(biāo)注噪聲也被模型完整吃進(jìn)去。尤其是標(biāo)注了背景類的場(chǎng)景土壤在不同波段的反射分布差異巨大模型學(xué)會(huì)了用波段組合模式去猜背景而不是真正理解葉片邊界。解決先用RGB部分加載COCO預(yù)訓(xùn)練權(quán)重把多光譜新增的兩個(gè)通道的輸入層做權(quán)重重置然后凍結(jié)主干前10層只訓(xùn)練分割頭和neck部分。等損失曲線平穩(wěn)后解凍全部層用小學(xué)習(xí)率0.0001微調(diào)。這個(gè)策略能把多光譜的增益真正發(fā)揮出來通常比全量從頭訓(xùn)練高出4到5個(gè)mAP點(diǎn)。5.2 16位TIFF直接喂進(jìn)模型所有葉片預(yù)測(cè)成背景現(xiàn)象訓(xùn)練loss不下降預(yù)測(cè)結(jié)果全圖都是黑色掩膜一片空白。檢查輸入圖像發(fā)現(xiàn)大部分區(qū)域全黑或過曝。原因OpenCV讀16位TIFF返回的dtype是uint16模型內(nèi)部默認(rèn)按uint8的0到255范圍做歸一化16位數(shù)據(jù)的數(shù)值范圍是0到65535模型把所有像素當(dāng)成“大于1”的異常值歸一化后幾乎全部壓到1信息全丟。解決手寫預(yù)處理腳本把五通道TIFF按2%到98%分位數(shù)拉伸成uint8再拼接成5通道輸入。這個(gè)坑在2.3節(jié)的處理流程里已經(jīng)解決但常有同學(xué)跳過預(yù)處理直接開始訓(xùn)練強(qiáng)烈建議訓(xùn)練前用cv2.imwrite輸出一張RGB合成圖目視檢查。5.3 切圖推理后小目標(biāo)計(jì)數(shù)重復(fù)一個(gè)蟲體被數(shù)成三只現(xiàn)象對(duì)大圖做滑窗切圖推理把小圖結(jié)果拼回原圖后切圖邊緣的蟲體出現(xiàn)重復(fù)計(jì)數(shù)最多能重復(fù)三倍。原因切圖窗口之間通常有20到50像素的重疊用來避免目標(biāo)在邊緣被截?cái)?。但合并結(jié)果時(shí)沒有做跨圖去重落在重疊區(qū)的蟲體在兩三張切圖里各被識(shí)別一次。解決合并階段按物體中心點(diǎn)坐標(biāo)聚類兩中心點(diǎn)距離小于10像素的認(rèn)為是同一個(gè)蟲體。實(shí)現(xiàn)方式是在4.1節(jié)的連通域分析上疊加一個(gè)去重循環(huán)把全部切圖的檢測(cè)結(jié)果先收集到同一坐標(biāo)系然后按中心點(diǎn)做空間哈希去重。另外一個(gè)更省事的方案是讓切圖重疊區(qū)保持0像素把確實(shí)被截?cái)嗟南x體交給后續(xù)的掩膜拼接邏輯處理但這樣就損失了切圖增強(qiáng)召回率的意義。5.4 換了個(gè)太陽角度模型預(yù)測(cè)結(jié)果大面積漂移現(xiàn)象上午10點(diǎn)采集的數(shù)據(jù)訓(xùn)練出的模型放到下午4點(diǎn)的田塊上預(yù)測(cè)病斑葉片被大量識(shí)別為背景蟲害葉片漏檢一半。原因多光譜反射率對(duì)光照角度和太陽高度角極其敏感。上午采集時(shí)紅邊波段的值域整體偏高模型學(xué)到了這個(gè)統(tǒng)計(jì)特征下午太陽角度變化后紅邊值域偏移模型認(rèn)為所有樣本分布異常輸出趨于保守。解決預(yù)測(cè)前不做任何圖像增強(qiáng)直接調(diào)整模型推理時(shí)的對(duì)比度歸一化參數(shù)把輸入圖像的分位數(shù)中心化到訓(xùn)練集統(tǒng)計(jì)值。根治辦法是在采集階段固定每天的采集時(shí)段比如只做上午9點(diǎn)到11點(diǎn)的窗口另外每次飛行前做白板校正。如果必須覆蓋全天場(chǎng)景訓(xùn)練數(shù)據(jù)必須包含不同時(shí)段樣本哪怕犧牲一部分單時(shí)段精度也要保全天魯棒性。5.5 Jetson Nano上部署推理顯存直接溢出現(xiàn)象在Jetson Nano 4GB版部署yolo11m-seg模型TensorRT推理時(shí)CUDA out of memory換成n分支勉強(qiáng)能跑但幀率只有3FPS。原因YOLOv11分割模型比檢測(cè)模型多一條掩膜分支顯存占用高出一大截。直接用官方PyTorch權(quán)重做推理時(shí)動(dòng)態(tài)shape的顯存分配沒有優(yōu)化4GB內(nèi)存根本不夠。解決導(dǎo)出TensorRT engine時(shí)固定輸入尺寸禁止動(dòng)態(tài)batch。batch_size固定為1輸入尺寸固定為640而不是1024開啟FP16量化。再極致一些可以把掩膜輸出插值操作挪到CPU上做GPU只保留網(wǎng)絡(luò)推理部分。實(shí)測(cè)固定shape后顯存占用可以從4.6GB壓到1.8GB幀率從3FPS提到15FPS配合2.3節(jié)的切圖推理能勉強(qiáng)滿足實(shí)時(shí)監(jiān)測(cè)。如果目標(biāo)是Rockchip這類ARM Linux平臺(tái)常見做法是在yocto系統(tǒng)里交叉編譯TensorRT或使用Rockchip的NPU工具鏈但別指望直接復(fù)用NVIDIA的engine文件。6. 把東西交出去系統(tǒng)部署的驗(yàn)證方式和最后一步校準(zhǔn)模型在開發(fā)機(jī)上跑通只是完成了一半田間系統(tǒng)要交付的是穩(wěn)定輸出。我的習(xí)慣是先在室內(nèi)測(cè)試集上跑全量數(shù)據(jù)確認(rèn)沒有類別崩潰和掩膜空洞問題后再帶著便攜屏和模型去種植戶的大棚里做三組現(xiàn)場(chǎng)驗(yàn)證一組正常光照、一組遮陰、一組噴灌后葉片帶水珠。帶水珠的工況最容易暴露問題水珠在近紅外波段恰好是高反射體會(huì)偽裝成蟲體邊緣。部署時(shí)導(dǎo)出TensorRT固定shape模型之后我會(huì)額外寫一個(gè)很小的校驗(yàn)?zāi)_本把導(dǎo)出前后模型的輸出結(jié)果做逐通道對(duì)比允許誤差控制在1e-2以內(nèi)。這個(gè)步驟能抓出TensorRT對(duì)某些自定義算子的精度退化。把最后一段推理結(jié)果保存腳本里加上一張“置信度直方圖”每隔30分鐘統(tǒng)計(jì)一次輸出分?jǐn)?shù)分布如果分布和訓(xùn)練時(shí)差異明顯說明現(xiàn)場(chǎng)工況已經(jīng)漂移出訓(xùn)練數(shù)據(jù)覆蓋范圍系統(tǒng)會(huì)在后臺(tái)提醒重新采集數(shù)據(jù)微調(diào)。最后一步是把蟲口數(shù)換算成發(fā)生程度。植保上一般按單葉蟲口數(shù)和病斑面積占比分成輕、中、重三級(jí)模型輸出的絕對(duì)數(shù)值并不直接等于防治決策信號(hào)。我現(xiàn)在交付的系統(tǒng)里都會(huì)加一段歸一化邏輯把蟲口數(shù)除以檢測(cè)葉片的總面積得到蟲口密度再查分級(jí)表輸出預(yù)警等級(jí)避免葉片大小差異導(dǎo)致的計(jì)數(shù)誤判。這個(gè)細(xì)節(jié)是多個(gè)項(xiàng)目甲方回頭找我們改需求的共同原因第一次做時(shí)很容易漏。希望這篇開發(fā)指南能幫你在自己的多光譜數(shù)據(jù)集上少走彎路從模型訓(xùn)練到最終交付都能穩(wěn)一點(diǎn)。本文還有配套的精品資源點(diǎn)擊獲取