飛機檢測數(shù)據(jù)集:YOLO格式訓(xùn)練與調(diào)參指南)
簡介這是一份面向計算機視覺研究者和深度學(xué)習(xí)學(xué)習(xí)者的紅外小目標(biāo)飛機檢測數(shù)據(jù)集聚焦紅外場景下低空小尺寸飛機的識別任務(wù)尤其適合小目標(biāo)檢測、紅外圖像分析與模型輕量化等方向。包內(nèi)按YOLO格式劃分訓(xùn)練集與驗證集配置文件標(biāo)明訓(xùn)練集包含16551張圖像路徑驗證集包含4952張圖像路徑類別為單一飛機可直接用于YOLO系列等主流目標(biāo)檢測框架的訓(xùn)練與驗證。壓縮包共包含2000個文件以926個xml標(biāo)注文件、926個txt標(biāo)簽文件、147個bmp紅外圖像文件和一個cache緩存文件為主體其中xml可轉(zhuǎn)為VOC格式txt為YOLO訓(xùn)練所需的標(biāo)簽bmp提供原始紅外小目標(biāo)圖像整體大小約37.4MB。目前已有169人學(xué)習(xí)使用入手即可獲得完整標(biāo)注、劃分配置與原始圖像能夠直接開展算法對比實驗有效節(jié)省自行整理和標(biāo)注數(shù)據(jù)的時間對關(guān)注紅外弱小目標(biāo)檢測的研究者尤具參考價值。1. 紅外小目標(biāo)飛機檢測數(shù)據(jù)集一份能直接開訓(xùn)的 YOLO 格式底料做紅外弱小目標(biāo)檢測的同行應(yīng)該都有過這種經(jīng)歷算法模型選好了loss 設(shè)計好了結(jié)果卡在數(shù)據(jù)上——自己標(biāo)紅外圖費眼睛不說小目標(biāo)在 256×256 里就占幾個像素框稍微偏一點 IoU 直接掉到零點幾標(biāo)注質(zhì)量根本沒法保證。這份 紅外小目標(biāo)飛機檢測數(shù)據(jù)集 train 解決的就是這個痛點它是一個按 VOC2007 目錄組織、已經(jīng)轉(zhuǎn)好 YOLO 格式標(biāo)注的飛機檢測數(shù)據(jù)集訓(xùn)練集 16551 張、驗證 4952 張全部是紅外場景下的飛機目標(biāo)類別就一個air。拿到手之后不需要再做格式轉(zhuǎn)換直接用 YOLOv5、YOLOv8 或者 mmrotate 的訓(xùn)練腳本就能跑起來。如果你正在做紅外告警、機場凈空監(jiān)測、低慢小目標(biāo)檢測這類項目或者想用一個干凈的單類紅外數(shù)據(jù)集來調(diào)通自己的訓(xùn)練流程這份數(shù)據(jù)是很好的起點。2. 數(shù)據(jù)集的真實構(gòu)成VOC 目錄、YOLO 標(biāo)簽和那 16551 張圖的可信度2.1 目錄結(jié)構(gòu)先看明白為什么說它是 VOC 組織格式從摘要里的配置信息能推斷出這個數(shù)據(jù)集的落盤方式。train: ./data/VOC2007/train.txt和val: ./data/VOC2007/test.txt這兩行說明圖片真實存放路徑在 VOC2007 目錄體系下而 train.txt / test.txt 是 YOLO 系列訓(xùn)練框架讀取的圖片清單文件。這也是 YOLOv5 / YOLOv8 官方數(shù)據(jù)組織方式之一從官方coco128.yaml的寫法沿襲而來。常見做法是這樣三步# 第一步看 train.txt 的前幾行確認(rèn)圖片路徑是絕對路徑還是相對路徑 head -n 5 train.txt # 第二步確認(rèn) label 文件是否和圖片一一對應(yīng) find . -name *.bmp | wc -l find . -name *.txt | wc -l # 第三步確認(rèn) JPEGImages 和 labels 目錄存在且命名規(guī)則匹配 ls ./data/VOC2007/JPEGImages | head -n 10 ls ./data/VOC2007/labels | head -n 10這里 train.txt 里每行是圖片的完整或相對路徑Y(jié)OLO 會拿這個路徑去找圖片然后把圖片路徑里的images替換成labels來找標(biāo)注文件。這是 YOLOv5 系列框架約定好的自動映射邏輯不需要你手動寫代碼去配對。所以關(guān)鍵檢查點在于圖片擴展名是.bmp還是.jpglabels 目錄下是不是同名.txt。這個數(shù)據(jù)集里正文列出的是683.bmp、956.bmp、898.bmp這類純數(shù)字命名說明原始采集就做了匿名處理。數(shù)據(jù)集項目數(shù)值說明圖片格式bmp紅外原始圖常見格式不經(jīng)過有損壓縮訓(xùn)練集規(guī)模16551 張對應(yīng) train.txt驗證集規(guī)模4952 張對應(yīng) test.txt目標(biāo)類別數(shù)1 類names 中只有一個air標(biāo)注格式Y(jié)OLO txt每行 class_id x_center y_center width height歸一化從這份配置看訓(xùn)練和驗證比大約是 76.9% / 23.1%這個比例在單類檢測任務(wù)里是比較健康的驗證集足夠大不會出現(xiàn)訓(xùn)練集漲點、驗證集波動劇烈的局面。2.2 YOLO 標(biāo)簽格式還原紅外小目標(biāo)的標(biāo)注粒度所有 YOLO 格式標(biāo)注的本質(zhì)是歸一化坐標(biāo)加寬高即每個目標(biāo)占一行五個數(shù)字分別是類別序號、框中心 x、框中心 y、框?qū)?、框高全部除以圖片寬高做了歸一化。這個數(shù)據(jù)集只有air一個類所以類別序號恒為 0。它的目標(biāo)框是小目標(biāo)尺度在紅外圖像中飛機通常只占幾十個像素甚至十幾個像素歸一化后寬高往往在 0.05 以下。# 隨便挑一張圖的標(biāo)簽看一眼分布 import os import numpy as np labels_dir ./data/VOC2007/labels label_files os.listdir(labels_dir) sample np.loadtxt(os.path.join(labels_dir, label_files[0])) print(該圖目標(biāo)數(shù)量:, sample.shape) if sample.ndim 2: # 每一列分別是 class_id, x_center, y_center, width, height print(歸一化寬高范圍:, sample[:, 3].min(), sample[:, 3].max(), sample[:, 4].min(), sample[:, 4].max())跑完這段腳本能看到目標(biāo)尺寸分布。如果歸一化后的 w 和 h 大多數(shù)在 0.02 到 0.08 之間說明這張紅外圖是典型的寬場景、遠(yuǎn)距離目標(biāo)。這種數(shù)據(jù)不能直接套用 COCO 上預(yù)訓(xùn)練模型的默認(rèn) anchor 尺度后面訓(xùn)練時需要對 anchor 做調(diào)整或者改用 anchor-free 的檢測頭。這個數(shù)據(jù)集跟常見的 CCD 可見光數(shù)據(jù)集最大的不同在于紅外圖像是單通道灰度圖目標(biāo)與背景的對比度由溫差決定而不是顏色或紋理。因此做數(shù)據(jù)增強時要小心顏色抖動類操作它們對紅外圖像基本無效反而可能把目標(biāo)邊緣抹淡。后面第 4 章講訓(xùn)練參數(shù)時會具體說怎么調(diào)。3. 把數(shù)據(jù)掛進(jìn)訓(xùn)練框架從 YAML 配置到起訓(xùn)一條龍3.1 掛載到 YOLOv8一份 YAML 搞定訓(xùn)練集與驗證集拿到這份數(shù)據(jù)后第一步不是寫代碼而是把數(shù)據(jù)掛載到檢測框架的接口上。YOLOv8 和 YOLOv5 都支持通過一個 YAML 文件聲明數(shù)據(jù)和模型配置。這里我以 YOLOv8 為例因為它的 detect 模塊對紅外小目標(biāo)的適配更友好# infrared_air.yaml train: ./data/VOC2007/train.txt val: ./data/VOC2007/test.txt # 類別數(shù) nc: 1 # 類別名 names: [air]注意如果 train.txt 里寫的是絕對路徑那么 YAML 里也用絕對路徑如果是相對路徑Y(jié)AML 路徑是相對你執(zhí)行訓(xùn)練命令的工作目錄而言的建議直接在項目根目錄下執(zhí)行避免嵌套路徑導(dǎo)致的 FileNotFoundError。然后直接起訓(xùn)練yolo detect train datainfrared_air.yaml modelyolov8n.pt epochs100 imgsz640 batch16這里modelyolov8n.pt表示加載 COCO 預(yù)訓(xùn)練權(quán)重做遷移學(xué)習(xí)雖然 COCO 里沒有紅外飛機類別但淺層特征邊緣、角點、明暗對比是可以遷移的。imgsz640是輸入分辨率如果你的紅外原圖本身是 640×512 或 320×256建議直接讀原圖尺寸訓(xùn)練不要強行 resize 到 640 以上因為紅外小目標(biāo)放大后容易模糊。3.2 自定義 Dataset 加載繞過 YOLO 框架直接看圖如果你不想用現(xiàn)成的 detect 腳本而是想自己寫訓(xùn)練循環(huán)、控制數(shù)據(jù)增強策略可以自己加載這個數(shù)據(jù)集。關(guān)鍵點在于讀取 train.txt 的路徑列表然后用 OpenCV 讀灰度圖配合解析同名 txt 標(biāo)簽做可視化驗證# custom_dataset.py import cv2 import numpy as np from pathlib import Path def load_infrared_dataset(list_file, labels_root): with open(list_file, r) as f: img_paths [line.strip() for line in f.readlines() if line.strip()] samples [] for img_path in img_paths: img_path Path(img_path) # 把圖片路徑中的 images 目錄替換為 labels 目錄得到標(biāo)注路徑 label_path Path(str(img_path).replace(images, labels)).with_suffix(.txt) if not label_path.exists(): print(f警告: {label_path} 不存在跳過) continue samples.append((str(img_path), str(label_path))) return samples def draw_yolo_boxes(img, label_path, img_shape): h, w img_shape[:2] boxes np.loadtxt(label_path).reshape(-1, 5) for box in boxes: x_c, y_c, bw, bh box[1] * w, box[2] * h, box[3] * w, box[4] * h x1 int(x_c - bw / 2) y1 int(y_c - bh / 2) x2 int(x_c bw / 2) y2 int(y_c bh / 2) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 1) return img if __name__ __main__: samples load_infrared_dataset(./data/VOC2007/train.txt, ./data/VOC2007/labels) print(有效樣本數(shù):, len(samples))這段代碼做了兩件事一是把 train.txt 的圖片路徑映射到 labels 目錄下同名 txt二是把 YOLO 歸一化坐標(biāo)還原成像素坐標(biāo)畫框便于人工檢查標(biāo)注是否偏離目標(biāo)。開發(fā)階段建議先跑這個腳本隨機抽查 50 張圖做可視化確認(rèn)標(biāo)注質(zhì)量沒問題再投喂給模型訓(xùn)練這一步能避免訓(xùn)練半天發(fā)現(xiàn)標(biāo)簽錯位的問題。3.3 VOC 格式轉(zhuǎn) YOLO 的兜底方案./data/VOC2007/這個路徑暗示原始標(biāo)注可能保留了 VOC 的 XML 格式Annotations 目錄如果你后續(xù)要改成多類檢測或者用 Detectron2、mmdetection 這類框架訓(xùn)練它們默認(rèn)吃 COCO JSON 或 VOC XML這時候需要把 YOLO txt 導(dǎo)回 VOC XML。比較省事的方式是反向解析# 用 roboflow 提供的轉(zhuǎn)換工具一條命令把 YOLO 轉(zhuǎn)成 VOC pip install pyyaml python -c from roboflow import Roboflow; ... # 需要聯(lián)網(wǎng)取工具包不過更推薦的離線做法是直接寫腳本遍歷 labels 目錄每讀一個 txt 生成一個 XML根節(jié)點是annotation子節(jié)點object里填nameair/name和bndbox坐標(biāo)值。坐標(biāo)要先乘回原圖寬高再轉(zhuǎn)成整數(shù)。這部分只在你換框架時才用得上如果你一直跑 YOLO 系列完全可以跳過。4. 訓(xùn)練參數(shù)怎么定紅外小目標(biāo)的特殊調(diào)參路線4.1 輸入尺寸和 anchor小目標(biāo)檢測的玄學(xué)在這里單類小目標(biāo)檢測跟通用檢測最大的區(qū)別在 anchor 尺度。COCO 預(yù)訓(xùn)練模型的 anchor 是為平均 50×50 像素以上的目標(biāo)設(shè)計的對于歸一化寬高只有 0.03 的紅外飛機目標(biāo)原始 anchor 完全失效。YOLOv8 是 anchor-free 的其實沒有 anchor 參數(shù)要調(diào)但 YOLOv5 需要。在 YOLOv5 里可以關(guān)掉 autoanchorpython train.py --data infrared_air.yaml --cfg yolov5n.yaml \ --weights yolov5s.pt --img 640 --batch 16 --epochs 100 \ --noautoanchor關(guān)閉 autoanchor 后YOLOv5 會使用配置文件里的默認(rèn) anchor此時小目標(biāo)的召回一般不會太差因為檢測頭本身有 80×80 的細(xì)粒度特征圖對應(yīng)原圖 8×8 像素的區(qū)域能覆蓋大多數(shù)紅外小目標(biāo)。如果發(fā)現(xiàn)漏檢嚴(yán)重再用 k-means 重新聚類 anchor# 在 YOLOv5 utils/autoanchor.py 中運行 k-means python utils/autoanchor.py --data infrared_air.yaml輸出的新 anchor 會打印在終端把它回填到模型 yaml 配置里再重新訓(xùn)練。這種做法對 YOLOv5 來說效果立竿見影聚類出來的 anchor 會更貼近歸一化寬高 0.02~0.06 的真實目標(biāo)分布。4.2 訓(xùn)練輪次、batch size、學(xué)習(xí)率權(quán)衡紅外小目標(biāo)數(shù)據(jù)單類、背景相對單一訓(xùn)練不需要像 COCO 那樣跑 300 輪一般 100~150 輪就夠了。batch size 取決于顯存yolov8n 在 16G 顯卡上 batch32 沒問題如果顯存小batch8 也行但要同步把學(xué)習(xí)率調(diào)低。給一個能直接用的組合輸入尺寸imgsz640或原圖分辨率如果原圖是 512 就 512batch size16 到 32 之間用梯度累積補償初始學(xué)習(xí)率YOLOv8 默認(rèn)lr00.01跑小數(shù)據(jù)集建議降到0.001防止前期震蕩數(shù)據(jù)增強關(guān)閉 mosaic 或者把 mosaic 概率設(shè)為 0.3因為紅外小目標(biāo)拼接后容易重疊、丟失目標(biāo)類別權(quán)重單類不存在類別不平衡不需要配class_weightsyolo detect train datainfrared_air.yaml modelyolov8n.pt \ epochs150 imgsz640 batch24 lr00.001 \ mosaic0.3 close_mosaic15close_mosaic15表示最后 15 輪關(guān)閉 mosaic 增強。這個參數(shù)是 YOLOv8 里專門為小目標(biāo)加的因為 mosaic 拼圖產(chǎn)生的偽邊界容易讓模型學(xué)到錯誤的上下文。同樣的邏輯也適用于 YOLOv5對應(yīng)參數(shù)是--mosaic 0.3但沒有 close_mosaic 這個選項只能自己在訓(xùn)練后期手動減小。4.3 數(shù)據(jù)增強配置別照搬 COCO 習(xí)慣COCO 上跑得好的增強策略在紅外數(shù)據(jù)集上可能翻車。具體來說HSV 變換、隨機色彩抖動這些增強在可見光數(shù)據(jù)集上能提升泛化能力但紅外圖是單通道HSV 只會改變灰度映射甚至?xí)涯繕?biāo)和背景的對比度拉低。常見做法是只保留空間類增強增強操作是否建議原因隨機翻轉(zhuǎn)建議飛機朝向不固定翻轉(zhuǎn)不改變目標(biāo)形態(tài)隨機縮放建議0.5~1.5 倍模擬不同距離下的目標(biāo)尺度隨機平移建議±10%增強位置泛化HSV 變化不建議紅外單通道無意義Mosaic謹(jǐn)慎0.3 以下拼接導(dǎo)致小目標(biāo)重疊MixUp不建議目標(biāo)透明化小目標(biāo)直接消失YOLOv8 的增強參數(shù)可以在 yaml 里關(guān)閉顏色類增強只開幾何增強這樣訓(xùn)練穩(wěn)定性會好很多val mAP 的抖動也會小。5. 避坑指南紅外小目標(biāo)數(shù)據(jù)集訓(xùn)練的四個高頻故障5.1 訓(xùn)練報錯 No labels found in ... 但標(biāo)簽?zāi)夸浢髅魇菨M的現(xiàn)象啟動訓(xùn)練后終端打印警告提示 train 目錄下沒找到標(biāo)簽訓(xùn)練直接卡住或精度恒為 0。原因YOLO 框架依靠圖片路徑到標(biāo)簽路徑的字符串映射。如果圖片在JPEGImages標(biāo)簽在labels而 train.txt 里的路徑是./data/VOC2007/JPEGImages/683.bmp框架會把JPEGImages替換成labels得到./data/VOC2007/labels/683.txt。一旦你改了目錄名比如把 labels 改成 Label映射鏈就斷了。解決讓 train.txt 里的路徑保持JPEGImages和labels這種成對命名或者將 train.txt 改為絕對路徑后重新檢查。5.2 驗證集 mAP 很高但實際圖片漏檢嚴(yán)重現(xiàn)象訓(xùn)練過程顯示 mAP0.5 達(dá)到 0.9 以上但拿到真實場景紅外圖測試時發(fā)現(xiàn)目標(biāo)漏檢尤其是極小目標(biāo)。原因數(shù)據(jù)集的驗證集和訓(xùn)練集來自同一采集批次背景分布高度相似模型學(xué)到的多半是背景模式而不是目標(biāo)本質(zhì)特征。解決調(diào)整訓(xùn)練策略將imgsz提高從 512 到 640打開多尺度訓(xùn)練--multi-scale如果仍然漏檢檢查標(biāo)簽里是否有大量寬度小于 3 像素的目標(biāo)這類目標(biāo)在下采樣到 640 時可能只剩 1 個像素需要把網(wǎng)絡(luò)下采樣倍數(shù)從 32 改成 16 或 8。5.3 訓(xùn)練 loss 下降到 0.02 但檢測框定位偏半個機身現(xiàn)象分類置信度正常但輸出的框中心點穩(wěn)定偏移IoU 上不去。原因標(biāo)簽中心點與真實目標(biāo)重心不一致標(biāo)注時往往框的是整個飛機輪廓而紅外圖像上飛機最亮的部分是發(fā)動機噴口模型學(xué)到的是高亮區(qū)域位置與框中心偏移了。解決做一次標(biāo)簽清洗用腳本把所有框稍微收縮 10% 到 20%讓框貼合目標(biāo)核心區(qū)域。這對小目標(biāo)檢測反而常常提高 mAP因為去除了背景干擾。# shrink_boxes.py: 收縮所有標(biāo)注框 15% import numpy as np from pathlib import Path label_dir Path(./data/VOC2007/labels) for txt_file in label_dir.glob(*.txt): boxes np.loadtxt(txt_file).reshape(-1, 5) if boxes.size 0: continue boxes[:, 3] * 0.85 boxes[:, 4] * 0.85 # 保存前注意檢查是否越界 boxes[:, [1, 3]] np.clip(boxes[:, [1, 3]], 0, 1) boxes[:, [2, 4]] np.clip(boxes[:, [2, 4]], 0, 1) np.savetxt(txt_file, boxes, fmt%.6f) print(完成)收縮框之后要重新可視化一遍確認(rèn)目標(biāo)沒有被切掉一半再做訓(xùn)練。5.4 數(shù)據(jù)增強后目標(biāo)直接融化在背景里現(xiàn)象訓(xùn)練時 mAP 波動特別大早期上升后突然掉點??梢暬鰪娸敵龊蟀l(fā)現(xiàn)目標(biāo)在增強圖上幾乎看不見。原因紅外圖對比度本來就低再做高斯模糊、隨機擦除等增強時小目標(biāo)被當(dāng)成噪聲抹掉了。解決在 YOLOv8 的增強參數(shù)里關(guān)閉hsv_h、hsv_s、hsv_v也不要用erasing類增強如果必須用隨機擦除擦除面積比控制在 0.05 以內(nèi)。6. 從零到一出圖跑完一次完整訓(xùn)練并驗證落盤結(jié)果數(shù)據(jù)集本身是訓(xùn)練流程的地基但落盤驗證才見真章。建議你按照下面流程強制走一遍確保拿到權(quán)重后能直接部署。先做數(shù)據(jù)完整性校驗確保訓(xùn)練集和測試集都沒有空標(biāo)注或越界標(biāo)注# validate_dataset.py import numpy as np from pathlib import Path def validate_label_file(txt_path, img_w, img_h): boxes np.loadtxt(txt_path).reshape(-1, 5) if boxes.size 0: return False # 檢查歸一化坐標(biāo)是否越界允許 0~1 之間 if (boxes[:, 1:] 0).any() or (boxes[:, 1:] 1).any(): return False return True train_list Path(./data/VOC2007/train.txt).read_text().splitlines() bad_count 0 for line in train_list: img_path Path(line.strip()) if not img_path.exists(): bad_count 1 continue label_path Path(str(img_path).replace(JPEGImages, labels)).with_suffix(.txt) if not label_path.exists(): bad_count 1 print(f異常樣本數(shù): {bad_count} / {len(train_list)})然后用 YOLOv8 的val模式驗證跑完訓(xùn)練后的 best.pt 權(quán)重yolo detect val datainfrared_air.yaml modelruns/detect/train/weights/best.pt \ imgsz640 batch8驗證輸出的 mAP 和混淆矩陣會寫入runs/detect/val目錄打開 confusion_matrix.png 能直接看到air這一類別的漏檢率。正常收斂時 mAP0.5 在 0.85 以上mAP0.5:0.95 在 0.6 左右。如果 mAP0.5 很高而 mAP0.5:0.95 很低說明模型對 IoU 閾值敏感也就是框定位精度不夠回到 5.3 的標(biāo)簽清洗思路。最后做一次真實推理選一張 val 集之外的圖片把輸出畫框疊加在原圖上保存yolo predict modelruns/detect/train/weights/best.pt \ source./test_images/083.bmp conf0.25 imgsz640如果 detect 框能穩(wěn)定落在飛機噴口高亮區(qū)域且不跳變就說明這份數(shù)據(jù)集的訓(xùn)練鏈路走通了。對紅外小目標(biāo)數(shù)據(jù)集來說訓(xùn)練時養(yǎng)成先看增強樣本再開長訓(xùn)練的習(xí)慣能少走很多彎路。每次拿到新數(shù)據(jù)集我都強制走一遍validate - visual check - short epochs - full epochs的順序短訓(xùn)練跑 20 輪先看 loss 能否降到 0.1 以下確認(rèn)鏈路沒問題再跑 150 輪這樣能省下大量返工時間。希望幫到你。本文還有配套的精品資源點擊獲取