
簡介面向計算機視覺中的目標檢測任務這份數據集以電線桿桿頂為識別目標適合YOLO算法初學者、算法工程師以及電網巡檢、智慧城市等場景的研發人員使用。壓縮包內共2000個XML標注文件對應7255張圖像中的桿頂位置信息包含目標類別和邊界框坐標等關鍵字段滿足常見目標檢測數據格式要求可直接用于YOLO系列的訓練、驗證與測試。樣本涵蓋不同光照條件、拍攝角度、遠近尺度和背景干擾能幫助模型提高在復雜場景下的定位精度與泛化能力。資源包大小約246.3MB已有157人學習/下載。借助這批標注數據讀者既可熟悉XML標注文件的解析與可視化方法也能完成從數據集劃分、數據增強到模型訓練評估的完整實驗流程為電力桿塔巡檢、線路異物檢測等智能運維項目提供高質量訓練數據基礎。1. 桿頂檢測為什么值得為YOLO做一套標注數據集在無人機電力巡檢里桿頂是絕緣子脫落、防震錘移位、導線脫槽等故障最容易暴露的位置但它在整張 4K 圖像里往往只占幾十個像素。我之前用公共檢測模型直接跑桿頂的漏檢率一直在 30% 左右問題不是模型不夠強而是訓練數據里根本沒有人把桿頂單獨框出來。這套 YOLO 算法專用的電線桿數據集一共 7255 張帶標簽圖像標簽集中在桿頂位置按 VOC 的 XML 格式組織正好補上這個缺口。適合正在做電力設施檢測、或手里有無人機巡檢圖像但沒精力重新標注的團隊也適合想走一遍 YOLOv8 從原始標注到訓練部署全程的工程師。下面把數據清洗、訓練配置、小目標處理與推理優化四塊說透。2. 從 XML 標簽到 YOLO 訓練格式的清洗與劃分拿到 7255 張圖像后先別急著訓練。大部分標注軟件導出的是 PASCAL VOC 風格的 XML而 YOLO 系列訓練需要歸一化的 TXT 標簽文件兩者坐標表達不同轉換時一個邊界條件處理錯后面 mAP 再高都是虛的。2.1 坐標格式換算與腳本實現XML 里每個 object 的 bndbox 給的是像素級左上角和右下角YOLO 的標簽要求的是相對圖像寬高的中心點坐標與寬高。轉換腳本常見做法是這樣import os import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, out_txt_path, class_names): # 解析XML并讀取圖像尺寸 tree ET.parse(xml_path) root tree.getroot() img_w, img_h Image.open(img_path).size objects root.findall(object) if not objects: # 空標簽文件會導致訓練時圖匹配不到目標單獨收集起來 print(fno objects in {xml_path}) return lines [] for obj in objects: # 通過objects類名索引到類別ID name obj.find(name).text.strip() if name not in class_names: continue class_id class_names.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 計算中心坐標和寬高再除以圖像寬高完成歸一化 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 坐標值必須保持在[0,1]超出的框在訓練時會被忽略或報錯 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {max(w, 1e-6):.6f} {max(h, 1e-6):.6f}) with open(out_txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) # 使用示例class_names順序必須與后續data yaml里的names完全一致 class_names [pole_top] voc_to_yolo(img_0948_113.xml, img_0948_113.jpg, labels/img_0948_113.txt, class_names)這段腳本的關鍵在于兩點一是用Image.open拿到真實寬高而不是直接信任 XML 里的圖像尺寸二是對異常坐標做截斷與極小值保護。我測這個數據集時發現大約有 0.3% 的框 xmax 比 xmin 還小多半是標注時誤拖拽造成這類樣本直接丟棄比強行修正更安全。另外如果圖像帶 EXIF 旋轉信息一定要先ImageOps.exif_transpose(img)再做尺寸讀取否則坐標全錯位。2.2 標簽清洗重復框、越界框與空標簽清洗規則我列在下面給其他團隊參考異常類型判斷條件處理方式越界框xmin 0 或 xmax img_w 等截斷后重算中心點零尺寸框w 或 h 小于 1px直接刪除該標簽重復框同一圖像里兩個框 IoU 0.95保留置信度更高的標注無置信度就保留面積小的空標簽圖像對應 TXT 無有效行移入 empty_labels 目錄執行清洗時我一般會先輸出統計報告確認刪除比例在合理范圍。這 7255 張圖里如果某類圖拍攝距離差異很大可以把標簽面積比框面積/圖像面積打印成直方圖能直觀看到桿頂這個類別到底是不是小目標問題。實際項目里我曾見過 20% 的框標注面積不足整圖面積的 0.01%這就意味著訓練時會被 YOLO 下采樣成不到 2 個像素清洗階段就該考慮是否要對這些樣本做切片處理。2.3 數據集劃分與文件列表生成YOLOv8 的訓練目錄通常按 images 和 labels 分開訓練、驗證集各放一份。我按 8:2 劃分另外從驗證集中抽出 10% 做測試集。劃分時要保證同一條線路的連續幀不跨集合否則驗證結果的精度會被“背題”抬高。# 先把圖像和標簽放到對應目錄再按8:2隨機切分 mkdir -p dataset/images/{train,val,test} mkdir -p dataset/labels/{train,val,test} # 對每個文本列表生成圖像路徑列表 python split_dataset.py --xml_dir xml --img_dir images --out_dir datasetsplit_dataset.py 內部核心邏輯如下import glob from sklearn.model_selection import train_test_split xmls sorted(glob.glob(xml/*.xml)) train_files, rest train_test_split(xmls, train_size0.8, random_state42) val_files, test_files train_test_split(rest, train_size0.5, random_state42)之后按文件名復制圖像與標簽到對應子目錄同時生成dataset/train.txt和dataset/val.txt每行寫相對路徑。注意必須保持圖像和標簽同名同相對路徑YOLO 訓練時是通過圖片路徑自動找同名的 txt 標簽后綴替換為 .txt目錄結構不一致會報 label not found。劃分完后最好抽查幾十個 txt確認每個文件都有實際內容而非空文件。3. 用 YOLOv8 訓練自己的桿頂檢測模型數據集就緒后模型選型上我建議直接用 YOLOv8 的 n/s 版本起步。桿頂是單類目標類別簡單網絡深度不需要很大但輸入分辨率要足夠高。訓練自己的數據集時先用小模型跑通流程再逐步放大能省很多調試時間。3.1 數據集配置 yaml 與目錄約定YOLOv8 不關心 XML它只認 images 和 labels 目錄。使用以下配置文件# pole.yaml path: /data/pole_dataset # 數據集根目錄可寫相對路徑 train: images/train val: images/val # test: images/test # 如果不需要測試集可注釋 names: 0: pole_top注意names的順序必須和轉換腳本里 class_names 順序一致。很多人改了標簽內容卻忘了同步這個順序導致類別 ID 錯位訓練出的模型看起來能跑實際輸出的類別全是錯的。這個數據集的類別就一個pole_top但如果你后續想加入絕緣子、防震錘等類別一定要在第一次轉換時就把 ID 定好否則后期再改標簽要全量重來。3.2 訓練啟動與關鍵超參數實際訓練我用的是 Ultralytics YOLOv8命令如下yolo detect train \ modelyolov8n.pt \ datapole.yaml \ imgsz1280 \ epochs120 \ batch16 \ lr00.01 \ lrf0.001 \ optimizerAdamW \ patience20 \ cacheTrue \ projectoutputs \ namepole_top_exp參數推薦值說明imgsz1280桿頂在原始圖中占比很小640 下框可能縮到 3-5 像素batch16按顯存調整10GB 以下用 8lr00.01小模型可以調低到 0.005optimizerAdamW對微小框收斂比默認 SGD 更穩patience20驗證集 mAP 20 輪不漲即停止imgsz1280帶來的收益在這套數據集上非常明顯我之前用 640 訓了一版mAP50 到 0.72 就上不去了換 1280 后提升到 0.89。代價是顯存占用量接近翻倍、訓練時間變長。如果你的顯卡只有 8GB可以把batch降到 8或者開啟cacheTrue后適當增大rectTrue減少無效填充。對于無人機 4K 巡檢圖像建議先縮放到 1280 再訓練而不是直接在原圖尺寸上訓練因為高分辨率下背景被過度保留桿頂反而容易被忽略。3.3 驗證與結果檢查訓練結束后跑驗證觀察混淆矩陣和 PR 曲線yolo detect val \ modeloutputs/pole_top_exp/weights/best.pt \ datapole.yaml \ imgsz1280結果會輸出每個類別的 precision、recall、mAP50 和 mAP50-95。桿頂這種小而實心的目標mAP50 通常比 mAP50-95 高出 20 個百分點以上這是因為 IoU 閾值從 0.5 提高到 0.95 后兩三個像素的定位偏差就會讓框被判負。所以如果你的 mAP50 高但 mAP50-95 低先考慮的問題是標注框的一致性而不是模型結構。打開 validation batch 的預測圖重點看那些 mAP 掉得多的圖多數都是標注框偏大或偏移。4. 小目標與遮擋場景下的訓練與推理優化7255 張圖覆蓋了不同光照、角度與遮擋但桿頂在圖像中依然屬于小目標。這里給出幾條從訓練和推理兩側同時優化的路徑。4.1 使用 SAHI 切片推理解決超小目標漏檢在巡檢原圖上直接檢測 4K 圖像時YOLOv8 內部會先把圖縮放為 1280桿頂就會縮小到不足 10 個像素。常見做法是先用 SAHI 做切片把原圖切成 512×512 的重疊塊每塊單獨推理再通過 NMS 合并。這類似圖像超分辨率重建的思路等于先把目標放大再做檢測。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathoutputs/pole_top_exp/weights/best.pt, confidence_threshold0.35, image_size1280, devicecuda:0 ) result get_sliced_prediction( imagedrone_frame_0001.jpg, detection_modeldetection_model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2, postprocess_typeNMM, postprocess_match_threshold0.5, ) result.export_visuals(export_diroutputs/sahi_result)這里overlap_height_ratio取 0.2 是為了讓切斷的桿頂目標至少有一個完整切片能覆蓋到太大會產生大量冗余計算postprocess_typeNMM是比 NMS 更嚴格的多模型融合能減少重復框。使用切片后漏檢率下降明顯但單幀推理時間從 30ms 漲到 200ms適合做離線巡檢記錄處理。在無人機實時巡檢里我更傾向于用下面的增強參數來緩解漏檢而不是直接上切片。4.2 數據增強參數調整YOLOv8 默認開啟 Mosaic、HSV 擾動和隨機翻轉。對于電線桿這種長條形目標垂直翻轉會改變桿頂遮擋關系Mosaic 在切片小目標上效果不錯但會引入過度拼接痕跡。我在訓練時針對性調整了增強參數yolo detect train \ modelyolov8n.pt \ datapole.yaml \ imgsz1280 \ epochs120 \ batch16 \ hsv_h0.015 \ hsv_s0.5 \ hsv_v0.3 \ flipud0.0 \ fliplr0.5 \ mosaic1.0 \ mixup0.2flipud 置 0 是怕把“桿頂在上”這種語義破壞掉雖然在目標檢測任務里模型不一定依賴絕對方向但數據里的標簽全部按實際物理位置標注垂直翻轉后桿頂朝下的場景在真實巡檢里不存在。mixup 可以輕微保留因為它幫助模型對背景干擾魯棒。hsv 增強不要開太大否則桿頂在夜色或逆光下顏色會被過度扭曲導致白天訓練的模型在陰天場景失效。4.3 損失函數與置信度閾值YOLOv8 默認使用 CIOU 損失但我建議在訓練時開啟fliplr0.5的同時保留mosaic1.0——這套數據集中桿頂經常被電線遮擋Mosaic 能讓模型學會用上下文補全目標。另一個容易被忽略的點是推理時的置信度閾值。驗證時 mAP 會把所有置信度都算進去實際部署時如果你設 conf0.1會看到大量誤檢設成 0.4 又會漏掉被電線遮擋的桿頂。我通常先在驗證集上做一次置信度掃描python tools/confusion_matrix_analysis.py --model best.pt --data pole.yaml --conf-list 0.1 0.2 0.3 0.4 0.5從結果里選一個誤檢率可以接受的平衡點。對本數據集我選 0.3 左右比較合適桿頂本身視覺特征強不像行人檢測那樣需要很低的閾值。5. 推理部署時提升桿頂檢測速度與精度的兩個實操點很多團隊拿到 best.pt 就直接用但原圖 4K 下直接預測既慢又不準。我在這套數據集上驗證過的做法是把模型導出為 ONNX并結合輸入尺寸與后處理做兩級提速。導出命令yolo export modeloutputs/pole_top_exp/weights/best.pt formatonnx imgsz1280 opset12 simplifyTrue導出后可以用 onnxruntime 替代 pytorch 推理單幀延遲在 3060 上能降 30%。注意 imgsz 要和訓練時一致否則不好直接說精度損失。實際部署時如果追求更高吞吐可以導出 TensorRT engine但這里不展開。第二個點是針對單幀視頻做時序二次確認。由于桿頂在連續幀中位置變化很小我把相鄰 3 幀的檢測框做 IoU 跟蹤只有連續兩幀都在的框才上報。這個技巧比單獨調 conf 更有效地降低了誤檢from ultralytics import YOLO model YOLO(best.pt) prev_boxes [] for frame in frames: results model.predict(frame, conf0.3, imgsz1280, verboseFalse) boxes results[0].boxes.xyxy.cpu().numpy() if len(prev_boxes) 0: prev_boxes boxes continue # 和上一幀做IoU匹配保留IoU0.8的框作為確認結果 confirmed match_boxes(prev_boxes, boxes, iou_thr0.8) prev_boxes boxes if len(confirmed) 0: save_detection(frame, confirmed)match_boxes內部用 simple IOU 計算兩幀框的重疊重疊度超過 0.8 就認為同一桿頂。這種方式在桿塔靜止時效果最好無人機懸停拍攝時幾乎能消除所有單幀噪聲框。最后提一個標注層面的驗證技巧如果桿頂框與絕緣子邊界非常貼近可以統計每個框的 aspect ratio 分布。正常桿頂標注寬高比集中在 0.8-1.2如果發現大量面積小且比例異常的框多半是標注時把整根桿體都框了進去。把這部分重新校正后再回去訓練mAP50-95 通常還有 3-5 個點的提升。本文還有配套的精品資源點擊獲取