飛機(jī)檢測(cè)數(shù)據(jù)集train:從標(biāo)注到Y(jié)OLO訓(xùn)練全流程)
簡(jiǎn)介這份紅外小目標(biāo)飛機(jī)檢測(cè)數(shù)據(jù)集面向從事紅外圖像目標(biāo)檢測(cè)的研究者與算法工程師尤其適合需要驗(yàn)證YOLO系列模型在弱小目標(biāo)場(chǎng)景下性能的開(kāi)發(fā)者。數(shù)據(jù)以VOC2007格式組織訓(xùn)練集16551張、驗(yàn)證集4952張類(lèi)別僅含air一類(lèi)可直接接入常見(jiàn)檢測(cè)框架進(jìn)行訓(xùn)練與評(píng)估。壓縮包共2000個(gè)文件包含926個(gè)xml標(biāo)注文件、926個(gè)txt標(biāo)簽文件、147個(gè)bmp紅外圖像及1個(gè)cache緩存文件整體約37.4MB標(biāo)注與圖像一一對(duì)應(yīng)便于快速構(gòu)建數(shù)據(jù)加載流程。目前已有169人學(xué)習(xí)下載。借助該數(shù)據(jù)集讀者可完成從數(shù)據(jù)解析、模型訓(xùn)練到指標(biāo)對(duì)比的完整實(shí)驗(yàn)鏈路尤其適合研究紅外弱小目標(biāo)檢測(cè)、驗(yàn)證注意力機(jī)制或特征增強(qiáng)模塊效果的場(chǎng)景也可作為論文復(fù)現(xiàn)與消融實(shí)驗(yàn)的基礎(chǔ)數(shù)據(jù)來(lái)源。1. 紅外小目標(biāo)飛機(jī)檢測(cè)數(shù)據(jù)集 train從一份標(biāo)注文件到能跑通的訓(xùn)練管線紅外小目標(biāo)飛機(jī)檢測(cè)數(shù)據(jù)集 train 這個(gè)標(biāo)題拆開(kāi)看是三個(gè)東西紅外成像、小目標(biāo)、飛機(jī)檢測(cè)外加一個(gè) train 劃分。它解決的是在低信噪比、目標(biāo)只有幾個(gè)到幾十個(gè)像素、幾乎沒(méi)有紋理和顏色信息的紅外圖像里把飛機(jī)從云層、地物和噪聲背景中框出來(lái)。適合誰(shuí)做機(jī)場(chǎng)周界監(jiān)控、低空預(yù)警、遙感紅外偵察、無(wú)人機(jī)反制這類(lèi)方向的算法工程師以及手里已經(jīng)拿到一份紅外標(biāo)注數(shù)據(jù)、想用 YOLO 系列或類(lèi)似檢測(cè)器跑通訓(xùn)練的人。我見(jiàn)過(guò)太多人卡在第一步數(shù)據(jù)拿到了但不知道標(biāo)注格式對(duì)不對(duì)、類(lèi)別怎么定、小目標(biāo)在訓(xùn)練時(shí)怎么不丟。這篇就按我實(shí)際做過(guò)的路徑把這份 train 數(shù)據(jù)從檢查、轉(zhuǎn)換、配置到訓(xùn)練、排錯(cuò)講清楚。2. 紅外小目標(biāo)飛機(jī)檢測(cè)數(shù)據(jù)集 train 的標(biāo)注格式與目錄結(jié)構(gòu)怎么核對(duì)2.1 先確認(rèn)標(biāo)注是 VOC XML 還是 YOLO TXT紅外小目標(biāo)數(shù)據(jù)集常見(jiàn)的標(biāo)注格式有兩種PASCAL VOC 的 XML 和 YOLO 的歸一化 TXT。你拿到 train 目錄后第一件事不是急著寫(xiě)訓(xùn)練腳本而是看標(biāo)注文件長(zhǎng)什么樣。如果目錄里是Annotations/加JPEGImages/大概率是 VOC如果是images/加labels/且 labels 里是每行class x_center y_center width height那就是 YOLO 格式。兩種格式的轉(zhuǎn)換邏輯完全不同搞錯(cuò)了后面全白費(fèi)。我一般會(huì)先跑一段統(tǒng)計(jì)腳本把圖像尺寸、標(biāo)注框數(shù)量、類(lèi)別分布一次性看清楚。紅外小目標(biāo)有個(gè)特點(diǎn)框特別小寬高經(jīng)常在 8 到 30 像素之間如果圖像本身是 640×512 或 1280×1024歸一化后的寬高可能只有 0.01 到 0.05。這個(gè)量級(jí)直接決定后面 anchor 和輸入尺寸怎么設(shè)。import os import xml.etree.ElementTree as ET from collections import Counter def inspect_voc(anno_dir): stats Counter() sizes [] for f in os.listdir(anno_dir): if not f.endswith(.xml): continue tree ET.parse(os.path.join(anno_dir, f)) root tree.getroot() w int(root.find(size/width).text) h int(root.find(size/height).text) sizes.append((w, h)) for obj in root.findall(object): name obj.find(name).text bbox obj.find(bndbox) bw int(bbox.find(xmax).text) - int(bbox.find(xmin).text) bh int(bbox.find(ymax).text) - int(bbox.find(ymin).text) stats[name] 1 stats[f{name}_w_{bw//10*10}] 1 print(類(lèi)別與尺寸分布:, stats) print(圖像尺寸樣本:, sizes[:5]) inspect_voc(train/Annotations)這段腳本做三件事遍歷 XML、統(tǒng)計(jì)每個(gè)類(lèi)別的框數(shù)量、按 10 像素分桶統(tǒng)計(jì)框?qū)挕_壿嬚f(shuō)明紅外小目標(biāo)的框?qū)挿植既绻性?10 到 20 像素說(shuō)明輸入網(wǎng)絡(luò)前不能做太激進(jìn)的下采樣。參數(shù)說(shuō)明bw//10*10是分桶技巧方便看分布如果你發(fā)現(xiàn)某個(gè)類(lèi)別只有個(gè)位數(shù)樣本訓(xùn)練時(shí)就要考慮過(guò)采樣或合并類(lèi)別。2.2 目錄結(jié)構(gòu)決定 DataLoader 怎么寫(xiě)一份規(guī)范的 train 數(shù)據(jù)我期望看到的是目錄/文件作用檢查點(diǎn)images/train訓(xùn)練圖像格式統(tǒng)一為 jpg 或 png無(wú)損壞labels/trainYOLO 標(biāo)注每張圖對(duì)應(yīng)一個(gè) txt空文件表示無(wú)目標(biāo)classes.txt類(lèi)別名順序必須和訓(xùn)練配置一致train.txt圖像路徑列表每行一個(gè)絕對(duì)或相對(duì)路徑如果標(biāo)注是 VOC你需要先轉(zhuǎn)成 YOLO。轉(zhuǎn)換時(shí)最容易翻車(chē)的地方是坐標(biāo)越界和浮點(diǎn)精度。紅外小目標(biāo)框本來(lái)就小x_center/w算出來(lái)如果有 6 位小數(shù)寫(xiě)文件時(shí)截?cái)嗟?6 位就夠但千萬(wàn)別四舍五入到 2 位否則小框直接消失。import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, img_w, img_h, class_map): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: continue cls_id class_map[name] b obj.find(bndbox) xmin float(b.find(xmin).text) ymin float(b.find(ymin).text) xmax float(b.find(xmax).text) ymax float(b.find(ymax).text) xc (xmin xmax) / 2.0 / img_w yc (ymin ymax) / 2.0 / img_h bw (xmax - xmin) / img_w bh (ymax - ymin) / img_h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) return lines邏輯說(shuō)明先讀 XML 的寬高再逐 object 算歸一化中心點(diǎn)和寬高。參數(shù)說(shuō)明class_map是類(lèi)別名到 id 的映射必須和classes.txt行號(hào)一致.6f保留 6 位小數(shù)是 YOLO 生態(tài)的通用做法。轉(zhuǎn)換完記得抽查幾張圖用可視化腳本把框畫(huà)回去確認(rèn)沒(méi)有偏移。3. 用 YOLOv8 在紅外小目標(biāo)飛機(jī)檢測(cè)數(shù)據(jù)集 train 上跑通第一輪訓(xùn)練3.1 環(huán)境與數(shù)據(jù)配置文件的寫(xiě)法YOLOv8 對(duì)紅外小目標(biāo)不是最優(yōu)解但勝在工程鏈路成熟、文檔多、排錯(cuò)快。我一般先用它跑一個(gè) baseline確認(rèn)數(shù)據(jù)管線沒(méi)問(wèn)題再換更針對(duì)小目標(biāo)的檢測(cè)頭或注意力模塊。環(huán)境上ultralytics裝最新穩(wěn)定版即可CUDA 版本和顯卡驅(qū)動(dòng)對(duì)齊別在這上面省時(shí)間。數(shù)據(jù)配置文件plane_ir.yaml這樣寫(xiě)path: /data/ir_plane train: images/train val: images/val nc: 1 names: 0: plane邏輯說(shuō)明path是數(shù)據(jù)集根目錄train和val是相對(duì)路徑。參數(shù)說(shuō)明nc是類(lèi)別數(shù)紅外飛機(jī)檢測(cè)通常就一類(lèi)如果你把民航、軍機(jī)、無(wú)人機(jī)分開(kāi)標(biāo)這里要對(duì)應(yīng)改。names的順序必須和 labels 里的 class id 一致否則訓(xùn)練出來(lái)的模型會(huì)把類(lèi)別搞反。3.2 訓(xùn)練命令與關(guān)鍵參數(shù)怎么設(shè)第一輪訓(xùn)練不要一上來(lái)就 300 epoch先跑 50 epoch 看 loss 曲線和驗(yàn)證集表現(xiàn)。命令如下yolo detect train \ dataplane_ir.yaml \ modelyolov8s.pt \ imgsz640 \ epochs50 \ batch16 \ lr00.01 \ lrf0.01 \ warmup_epochs3 \ box7.5 \ cls0.5 \ dfl1.5 \ mosaic0.5 \ scale0.3 \ degrees0.0 \ translate0.1 \ fliplr0.5 \ flipud0.0 \ hsv_h0.0 \ hsv_s0.0 \ hsv_v0.0 \ projectruns/ir_plane \ namebaseline邏輯說(shuō)明紅外圖像沒(méi)有顏色信息所以hsv_h/s/v全部關(guān)掉開(kāi)了反而引入噪聲。mosaic0.5是折中值小目標(biāo)用 mosaic 容易把目標(biāo)拼到邊緣導(dǎo)致截?cái)?.5 比默認(rèn) 1.0 穩(wěn)。scale0.3控制隨機(jī)縮放幅度紅外小目標(biāo)本身像素少縮放太狠會(huì)丟。flipud0.0是因?yàn)榧t外圖像上下翻轉(zhuǎn)后天空和地面的熱分布不符合物理規(guī)律除非你的數(shù)據(jù)本身就是多角度采集。參數(shù)說(shuō)明imgsz640是起點(diǎn)如果你顯存夠可以試 1024小目標(biāo)在更高分辨率下召回會(huì)好一些但速度下降明顯。batch16根據(jù)顯存調(diào)8G 顯存跑 640 大概能到 16不夠就降到 8。lr00.01是 SGD 的初始學(xué)習(xí)率用 AdamW 的話改成 0.001。box7.5是框回歸損失權(quán)重小目標(biāo)定位難可以適當(dāng)提到 8.0 到 10.0 試。3.3 訓(xùn)練過(guò)程中看什么指標(biāo)跑起來(lái)之后重點(diǎn)看三個(gè)東西train/box_loss是否穩(wěn)定下降、metrics/mAP50是否在 20 epoch 后開(kāi)始爬、val/box_loss和train/box_loss的差距。紅外小目標(biāo)常見(jiàn)的情況是 mAP50 能到 0.7 以上但 mAP50-95 很低因?yàn)榭虻?IoU 很難做高。這不是訓(xùn)練失敗是小目標(biāo)的固有難點(diǎn)。如果 20 epoch 后 mAP50 還在 0.1 以下先別調(diào)模型回去查數(shù)據(jù)。我遇到過(guò)標(biāo)注框整體偏移 2 像素的情況人眼看不出但歸一化后小框的 IoU 直接掉一半。用可視化腳本把預(yù)測(cè)框和標(biāo)注框畫(huà)在同一張圖上一眼就能看出來(lái)。4. 紅外小目標(biāo)飛機(jī)檢測(cè)數(shù)據(jù)集 train 的避坑與排查記錄4.1 坑一小目標(biāo)在 letterbox 后消失現(xiàn)象訓(xùn)練時(shí) loss 正常下降但驗(yàn)證集幾乎檢不出目標(biāo)。原因YOLO 默認(rèn)的 letterbox 會(huì)把圖像縮放到 640×640如果原圖是 1280×1024縮放后小目標(biāo)可能只剩 4 到 5 像素再經(jīng)過(guò) backbone 的 32 倍下采樣特征圖上就沒(méi)了。解決把imgsz提到 1024 或 1280或者改用rectTrue保持長(zhǎng)寬比、減少無(wú)效填充。更徹底的做法是換小目標(biāo)檢測(cè)頭比如加 P2 層。4.2 坑二空標(biāo)注文件被當(dāng)成負(fù)樣本現(xiàn)象模型在無(wú)目標(biāo)區(qū)域瘋狂出框誤報(bào)率高。原因YOLO 訓(xùn)練時(shí)空 txt 文件會(huì)被當(dāng)作負(fù)樣本但如果你的數(shù)據(jù)里空?qǐng)D比例過(guò)高模型會(huì)學(xué)到“大部分地方?jīng)]目標(biāo)”的先驗(yàn)導(dǎo)致漏檢。解決統(tǒng)計(jì)空標(biāo)注比例如果超過(guò) 30%要么補(bǔ)充正樣本要么在 DataLoader 里對(duì)空?qǐng)D降采樣。我一般會(huì)把空?qǐng)D比例控制在 10% 到 20%。4.3 坑三類(lèi)別名大小寫(xiě)不一致現(xiàn)象訓(xùn)練能跑但推理時(shí)類(lèi)別顯示為plane或Plane混亂。原因classes.txt里寫(xiě)的是Planeyaml 里寫(xiě)的是planeYOLO 按 yaml 為準(zhǔn)但可視化工具可能讀另一個(gè)。解決統(tǒng)一用小寫(xiě)并且在轉(zhuǎn)換腳本里做一次name.lower()。這個(gè)坑不致命但交付時(shí)很尷尬。4.4 坑四驗(yàn)證集和訓(xùn)練集來(lái)自同一段視頻現(xiàn)象驗(yàn)證集 mAP 很高實(shí)際部署掉點(diǎn)嚴(yán)重。原因紅外視頻連續(xù)幀之間高度相似隨機(jī)劃分會(huì)導(dǎo)致訓(xùn)練集和驗(yàn)證集有大量近似幀。解決按視頻段或時(shí)間戳劃分確保驗(yàn)證集的場(chǎng)景、時(shí)段、天氣和訓(xùn)練集不重疊。這個(gè)坑我踩過(guò)兩次血淚經(jīng)驗(yàn)是寧可驗(yàn)證集小一點(diǎn)也要保證獨(dú)立性。4.5 坑五數(shù)據(jù)增強(qiáng)把目標(biāo)翻沒(méi)了現(xiàn)象訓(xùn)練中期 loss 突然震蕩。原因mosaic加mixup同時(shí)開(kāi)小目標(biāo)被拼到圖像邊緣后被裁剪掉模型學(xué)到的是不完整目標(biāo)。解決小目標(biāo)場(chǎng)景下mosaic不超過(guò) 0.5mixup直接關(guān)掉copy_paste可以開(kāi) 0.1 到 0.3 補(bǔ)充正樣本。增強(qiáng)策略要服務(wù)于數(shù)據(jù)特性不能照搬 COCO 的配置。5. 從 baseline 到可用模型紅外小目標(biāo)檢測(cè)的進(jìn)階調(diào)優(yōu)技巧第一輪跑通之后別急著堆 epoch。我一般會(huì)做三件事?lián)Q輸入分辨率、加 P2 小目標(biāo)層、用切片推理驗(yàn)證。換分辨率是最直接的。把imgsz從 640 提到 1024mAP50 通常能漲 5 到 10 個(gè)點(diǎn)但推理速度會(huì)掉一半。如果你的場(chǎng)景對(duì)實(shí)時(shí)性要求不高比如離線巡檢直接上 1280。如果要求實(shí)時(shí)考慮用 TensorRT 量化INT8 之后 1024 分辨率也能跑到 30 FPS 以上。加 P2 層需要改模型結(jié)構(gòu)。YOLOv8 的配置文件在ultralytics/cfg/models/v8/yolov8-p2.yaml把 P2 的檢測(cè)頭加上特征圖從 80×80 變成 160×160小目標(biāo)召回明顯提升。代價(jià)是顯存和計(jì)算量增加batch 可能要降到 8。我試過(guò)在紅外飛機(jī)數(shù)據(jù)上P2 版本比原版 mAP50-95 高 4 個(gè)點(diǎn)左右。切片推理是部署階段的技巧。把大圖切成 512×512 的小塊逐塊推理再合并能有效提升小目標(biāo)檢出率。SAHI 這個(gè)庫(kù)可以直接用但要注意重疊區(qū)域的框合并邏輯IoU 閾值設(shè) 0.5 到 0.6太低會(huì)重復(fù)框太高會(huì)漏合并。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/ir_plane/baseline/weights/best.pt, confidence_threshold0.25, devicecuda:0 ) result get_sliced_prediction( test_ir.jpg, model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2 ) result.export_visuals(export_dirruns/sahi_vis)邏輯說(shuō)明SAHI 把圖像切片后分別推理再按 NMS 合并。參數(shù)說(shuō)明slice_height/width根據(jù)你的目標(biāo)尺寸定目標(biāo)平均 20 像素的話512 的切片里目標(biāo)占比合適overlap_ratio0.2是經(jīng)驗(yàn)值太小會(huì)切掉目標(biāo)太大增加計(jì)算量。confidence_threshold0.25比訓(xùn)練時(shí)的 0.5 低因?yàn)榍衅髥螇K置信度會(huì)下降合并時(shí)再篩。最后說(shuō)一個(gè)驗(yàn)證習(xí)慣每次調(diào)完參數(shù)不要只看 mAP把誤報(bào)和漏報(bào)的圖各抽 20 張出來(lái)看。紅外小目標(biāo)的誤報(bào)往往來(lái)自云邊緣和地物熱源漏報(bào)集中在目標(biāo)與背景溫差小的場(chǎng)景。看多了你就知道下一步該補(bǔ)數(shù)據(jù)還是改模型。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取