數(shù)據(jù)集:XML標(biāo)注轉(zhuǎn)YOLO格式實(shí)戰(zhàn)與避坑指南)
簡(jiǎn)介YOLO目標(biāo)檢測(cè)可直接使用的帶鋼表面缺陷數(shù)據(jù)集面向計(jì)算機(jī)、電子信息工程、數(shù)學(xué)等專(zhuān)業(yè)學(xué)生適用于課程設(shè)計(jì)、期末大作業(yè)與畢業(yè)設(shè)計(jì)。資源包含1800張帶鋼表面缺陷圖像及對(duì)應(yīng)XML標(biāo)注文件并附BMP格式圖像副本和1個(gè)數(shù)據(jù)庫(kù)文件壓縮包文件總數(shù)2000大小78.62MB標(biāo)注框質(zhì)量高拿到后無(wú)需額外標(biāo)注即可投入YOLO訓(xùn)練與驗(yàn)證。目前已有1029人學(xué)習(xí)/下載多用于表面缺陷識(shí)別、工業(yè)質(zhì)檢等目標(biāo)檢測(cè)場(chǎng)景。使用時(shí)可對(duì)照J(rèn)PG/BMP圖像與XML標(biāo)注便于檢查類(lèi)別與邊界框相比從零采集標(biāo)注能大幅節(jié)省數(shù)據(jù)準(zhǔn)備時(shí)間讓讀者把精力集中在模型搭建、參數(shù)調(diào)優(yōu)與實(shí)驗(yàn)對(duì)比上。雙格式圖像也方便在OpenCV、Python等環(huán)境中預(yù)處理和增強(qiáng)是完成算法類(lèi)課設(shè)、期末設(shè)計(jì)或論文實(shí)驗(yàn)的實(shí)用基礎(chǔ)數(shù)據(jù)。1. 帶鋼表面缺陷檢測(cè)這份數(shù)據(jù)集為什么值得你花十分鐘看代碼做帶鋼表面缺陷檢測(cè)的課程設(shè)計(jì)最痛苦的環(huán)節(jié)往往不是模型選型而是數(shù)據(jù)。網(wǎng)上公開(kāi)的帶鋼缺陷數(shù)據(jù)集要么是沒(méi)標(biāo)注的原始圖片要么是標(biāo)注格式不對(duì)拿回來(lái)還得花兩三天重新畫(huà)框。這份資源是1800張帶鋼表面缺陷圖加對(duì)應(yīng)的XML標(biāo)注文件標(biāo)注框質(zhì)量較高能直接喂給YOLO做訓(xùn)練。對(duì)于計(jì)算機(jī)、電子信息工程、數(shù)學(xué)專(zhuān)業(yè)的學(xué)生來(lái)說(shuō)課程設(shè)計(jì)、期末大作業(yè)、畢設(shè)里需要跑通目標(biāo)檢測(cè)流程的這份數(shù)據(jù)能幫你跳過(guò)最煩人的數(shù)據(jù)準(zhǔn)備階段把精力集中在模型調(diào)參和檢測(cè)效果上。我看到文件名里有Sc、In、PS這類(lèi)前綴這是帶鋼缺陷領(lǐng)域的常見(jiàn)分類(lèi)標(biāo)識(shí)。Sc代表氧化皮ScaleIn代表壓痕IndentationPS代表劃痕Puncture/Scratch這類(lèi)缺陷的形態(tài)差異較大對(duì)目標(biāo)檢測(cè)模型來(lái)說(shuō)是個(gè)比較標(biāo)準(zhǔn)的單類(lèi)或多類(lèi)檢測(cè)任務(wù)。整個(gè)資源的核心價(jià)值就一句話(huà)圖片質(zhì)量高、標(biāo)注框貼合目標(biāo)、格式兼容YOLO系訓(xùn)練流程拿到手就能開(kāi)始搞。2. 數(shù)據(jù)集底細(xì)六類(lèi)缺陷與XML標(biāo)注的邊界2.1 缺陷類(lèi)型分布與圖片規(guī)格這批數(shù)據(jù)以BMP圖像為主文件名前綴直接對(duì)應(yīng)缺陷類(lèi)別。從文件命名規(guī)律來(lái)看Sc系列是氧化皮In系列是壓痕PS系列是劃痕類(lèi)缺陷。每張圖片對(duì)應(yīng)一個(gè)同名XML文件XML里記錄了目標(biāo)的邊界框坐標(biāo)和類(lèi)別名稱(chēng)這個(gè)目錄結(jié)構(gòu)是典型的Pascal VOC格式組織方式。圖片規(guī)格方面帶鋼表面缺陷數(shù)據(jù)集的原始圖分辨率通常在200×200左右這是因?yàn)閹т摫砻嫒毕輽z測(cè)的工業(yè)場(chǎng)景里缺陷目標(biāo)本身就比較小高分辨率大圖反而會(huì)稀釋缺陷的像素占比。200×200的尺寸對(duì)YOLO系列來(lái)說(shuō)不需要額外做太多預(yù)處理直接訓(xùn)練即可。這里提個(gè)醒如果你拿到手的圖片分辨率不一樣先統(tǒng)一尺寸或者調(diào)整anchor參數(shù)不要直接硬訓(xùn)。XML標(biāo)注文件是VOC格式的核心每個(gè)目標(biāo)框記錄四個(gè)坐標(biāo)值xmin、ymin、xmax、ymax外加一個(gè)name字段標(biāo)記缺陷類(lèi)別。這個(gè)格式跟YOLO訓(xùn)練直接需要的txt格式有一段轉(zhuǎn)換距離但轉(zhuǎn)換腳本屬于常規(guī)操作后面第三章會(huì)給出完整代碼。2.2 標(biāo)注質(zhì)量怎么看框貼合度檢查方法判斷一個(gè)標(biāo)注數(shù)據(jù)集能不能直接用不是看文件多不多而是看框跟缺陷邊緣的貼合度。我一般先在本地用可視化腳本把所有XML標(biāo)注畫(huà)回到原圖上重點(diǎn)看三類(lèi)問(wèn)題框是不是比缺陷實(shí)際區(qū)域大一圈、是不是漏標(biāo)了部分缺陷、以及類(lèi)別標(biāo)簽有沒(méi)有標(biāo)錯(cuò)。做法是讀取XML里的坐標(biāo)用OpenCV的rectangle函數(shù)把框畫(huà)到原圖上然后拼接成一張大圖人工過(guò)一遍。這個(gè)步驟花不了十分鐘但能避免訓(xùn)練到一半發(fā)現(xiàn)loss降不下去最后排查出來(lái)是標(biāo)注質(zhì)量問(wèn)題。這套可視化檢查腳本在壓縮包內(nèi)如果沒(méi)帶可以自己寫(xiě)一個(gè)代碼量不大。常見(jiàn)做法是抽樣20到30張圖做人工檢查。如果缺陷區(qū)域邊緣跟框偏差在3像素以?xún)?nèi)說(shuō)明標(biāo)注質(zhì)量合格如果偏差過(guò)大要么是原始標(biāo)注工具不同導(dǎo)致的系統(tǒng)誤差要么是標(biāo)注員本身畫(huà)框習(xí)慣就是留白較多。YOLO對(duì)這種框的容忍度還行因?yàn)橛?xùn)練時(shí)錨框回歸會(huì)學(xué)習(xí)這個(gè)偏移量但如果整體偏差超過(guò)10像素建議重新標(biāo)注或者放棄這部分?jǐn)?shù)據(jù)。2.3 為什么這份資源不用做數(shù)據(jù)清洗工業(yè)場(chǎng)景下采集的帶鋼表面圖像光照變化、油污、氧化皮脫落等因素都會(huì)導(dǎo)致圖片質(zhì)量參差不齊。但這份資源的圖片已經(jīng)做過(guò)一輪篩選從文件命名和圖片內(nèi)容來(lái)看背景相對(duì)干凈缺陷目標(biāo)清晰沒(méi)有出現(xiàn)模糊到無(wú)法標(biāo)注的情況。數(shù)據(jù)清洗這個(gè)環(huán)節(jié)能省掉不代表可以完全不檢查。我的習(xí)慣是把所有圖片尺寸打出來(lái)看有沒(méi)有異常分辨率的混入再把所有XML解析一遍看坐標(biāo)有沒(méi)有超出圖片邊界的。這兩個(gè)檢查用腳本跑一遍處理異常情況的時(shí)間不超過(guò)五分鐘但能避免訓(xùn)練時(shí)出現(xiàn)數(shù)組越界這種莫名其妙的報(bào)錯(cuò)。3. XML標(biāo)注轉(zhuǎn)YOLO格式轉(zhuǎn)換腳本與四個(gè)邊界坑3.1 VOC轉(zhuǎn)YOLO的目錄結(jié)構(gòu)和轉(zhuǎn)換腳本這份數(shù)據(jù)集的XML是VOC格式但YOLO訓(xùn)練需要的是txt格式每行一個(gè)目標(biāo)格式是“類(lèi)別id 中心點(diǎn)x 中心點(diǎn)y 框?qū)?框高”后面四個(gè)值都是相對(duì)圖片寬高的歸一化數(shù)值。第一步先把目錄整理成YOLO的標(biāo)準(zhǔn)輸入結(jié)構(gòu)dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ ├── classes.txt └── train.txt ├── val.txtimport xml.etree.ElementTree as ET import os from tqdm import tqdm def voc_to_yolo(xml_path, out_dir, class_names): tree ET.parse(xml_path) root tree.getroot() # 取圖片尺寸 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) img_name os.path.splitext(os.path.basename(xml_path))[0] out_txt os.path.join(out_dir, img_name .txt) with open(out_txt, w) as f: for obj in root.iter(object): cls obj.find(name).text if cls not in class_names: continue cls_id class_names.index(cls) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 轉(zhuǎn)成YOLO格式中心點(diǎn) 寬高全部歸一化 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 if x_center 0 or y_center 0 or w 0 or h 0: print(f警告: {img_name} 中存在非法坐標(biāo)) continue f.write(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n) class_names [Sc, In, PS, Pa, Cr, RS] # 按你的實(shí)際類(lèi)別列表調(diào)整這段代碼的邏輯是逐條讀取XML里的目標(biāo)框把左上右下角坐標(biāo)轉(zhuǎn)換成歸一化的中心點(diǎn)加寬高格式最后寫(xiě)入txt文件。參數(shù)說(shuō)明class_names的順序直接決定txt里類(lèi)別id的映射關(guān)系訓(xùn)練時(shí)配置文件的classes順序必須跟這里保持一致否則模型會(huì)學(xué)錯(cuò)類(lèi)別。圖片尺寸必須取XML里size節(jié)點(diǎn)的值不要自己用PIL去讀圖片計(jì)算因?yàn)閄ML里的標(biāo)注坐標(biāo)是基于原始圖片的如果比例對(duì)不上轉(zhuǎn)換出來(lái)的坐標(biāo)全錯(cuò)。3.2 四個(gè)邊界條件坐標(biāo)越界、空標(biāo)注、重復(fù)類(lèi)別、文件名不匹配實(shí)際跑轉(zhuǎn)換腳本時(shí)最怕的是安靜地轉(zhuǎn)換完不報(bào)錯(cuò)訓(xùn)練時(shí)卻出現(xiàn)問(wèn)題。第一是坐標(biāo)越界標(biāo)注框的中心點(diǎn)或?qū)捀咚愠鰜?lái)是負(fù)數(shù)或者超出了1.0這種通常要么是原始XML坐標(biāo)異常要么是圖片尺寸讀取錯(cuò)誤。我一般會(huì)在轉(zhuǎn)換后加一個(gè)校驗(yàn)?zāi)_本把所有txt里每行數(shù)字的范圍打印出來(lái)超過(guò)[0,1]區(qū)間直接標(biāo)紅。第二是空標(biāo)注文件部分圖片可能沒(méi)有目標(biāo)轉(zhuǎn)換后txt是空文件。YOLO訓(xùn)練允許這種圖片存在但前提是數(shù)據(jù)加載器的配置里要允許20%左右的空?qǐng)D比例不然訓(xùn)練時(shí)這些圖會(huì)被跳過(guò)間接減少了你的有效訓(xùn)練數(shù)據(jù)量。帶鋼表面缺陷數(shù)據(jù)里空?qǐng)D不多但需要留意。第三是重復(fù)類(lèi)別比如同一張XML里出現(xiàn)Sc和Scale兩種寫(xiě)法但屬于同一類(lèi)缺陷。轉(zhuǎn)換腳本里class_names沒(méi)有匹配上就會(huì)跳過(guò)該目標(biāo)導(dǎo)致丟失標(biāo)注。處理方式是用腳本把所有XML里的name字段去重打印出來(lái)確認(rèn)類(lèi)別叫法統(tǒng)一后再映射。第四是文件名不匹配圖片是Sc_109.bmp標(biāo)注是Sc_109.xml但轉(zhuǎn)換后txt的文件名必須跟圖片名完全一致包括大小寫(xiě)和后綴處理。Windows環(huán)境下尤其容易出問(wèn)題因?yàn)榇笮?xiě)不敏感Linux下訓(xùn)練卻嚴(yán)格區(qū)分建議轉(zhuǎn)換前統(tǒng)一轉(zhuǎn)小寫(xiě)。4. 避坑排查YOLO訓(xùn)練中碰到的數(shù)據(jù)側(cè)問(wèn)題4.1 現(xiàn)象訓(xùn)練loss降不下去在0.5到1.0之間來(lái)回震蕩原因排查下來(lái)多半是類(lèi)別id映射混亂。XML里的類(lèi)別順序跟訓(xùn)練配置里的classes順序?qū)Σ簧夏P桶淹粋€(gè)缺陷在不同epoch里當(dāng)成了不同類(lèi)別在學(xué)。解決方式是回到轉(zhuǎn)換腳本里把class_names固定成一份文件訓(xùn)練配置從這份文件讀取兩邊保持一致??梢杂靡粭l命令驗(yàn)證隨機(jī)抽查五張圖的txt內(nèi)容人工比對(duì)類(lèi)別id對(duì)應(yīng)的缺陷名是否跟圖片內(nèi)容一致。4.2 現(xiàn)象mAP很高但實(shí)際檢測(cè)時(shí)框的位置整體偏移這個(gè)問(wèn)題我之前在帶鋼缺陷項(xiàng)目踩過(guò)。原因是訓(xùn)練時(shí)用了數(shù)據(jù)增強(qiáng)里的隨機(jī)裁剪但裁剪后沒(méi)有同步更新標(biāo)注框的坐標(biāo)。YOLO自帶的mosaic和隨機(jī)仿射變換都是自動(dòng)處理標(biāo)注的但如果你在數(shù)據(jù)加載里自己加了裁剪邏輯就得手動(dòng)調(diào)整box坐標(biāo)。帶鋼表面缺陷圖片里缺陷往往在圖片邊緣訓(xùn)練增強(qiáng)時(shí)一旦裁掉一部分但label框坐標(biāo)沒(méi)同步縮小檢測(cè)時(shí)框自然就偏了。4.3 現(xiàn)象驗(yàn)證集上漏檢多尤其PS劃痕類(lèi)缺陷分析下來(lái)是劃痕缺陷長(zhǎng)寬比極端是長(zhǎng)條形目標(biāo)默認(rèn)anchor尺寸覆蓋不到。解決方式有兩個(gè)方向一是把訓(xùn)練集的wh聚類(lèi)一下用k-means重新算anchor參數(shù)二是調(diào)整anchor的寬高比例增加長(zhǎng)寬比大的anchor。YOLOv5以后版本還能開(kāi)autoanchor讓它自己聚類(lèi)但小數(shù)據(jù)集下還是建議手動(dòng)確認(rèn)聚類(lèi)結(jié)果別盲目自動(dòng)計(jì)算。4.4 現(xiàn)象xml讀取出來(lái)是亂碼或者解析報(bào)錯(cuò)帶鋼數(shù)據(jù)集的XML文件如果是從其他工具生成的有可能文件頭帶了BOM標(biāo)記或者編碼不是UTF-8。此時(shí)ET.parse會(huì)在第一行就報(bào)錯(cuò)。解決方式是先打開(kāi)文件讀文本用正則把非法字符清掉再交給ElementTree處理。這段代碼異常處理要寫(xiě)全常見(jiàn)的XML格式錯(cuò)誤基本都是編碼或者特殊轉(zhuǎn)義字符引起的。5. 訓(xùn)練工程落地YOLOv5配置與數(shù)據(jù)劃分實(shí)操5.1 數(shù)據(jù)劃分比例和ld無(wú)法直接讀取BMP時(shí)怎么辦1800張圖的數(shù)據(jù)量不大按811劃分訓(xùn)練、驗(yàn)證、測(cè)試集比較合理。劃分后訓(xùn)練集1440張驗(yàn)證集180張測(cè)試集180張。帶鋼表面缺陷類(lèi)別少、目標(biāo)小這個(gè)數(shù)據(jù)量跑YOLOv5s或者YOLOv8s足夠用了再大的模型容易過(guò)擬合。YOLO系默認(rèn)支持的圖像格式是jpg和png但資源里的原始圖片是BMP。YOLO在數(shù)據(jù)加載時(shí)如果無(wú)法解碼BMP會(huì)報(bào)類(lèi)似“cannot identify image file”的錯(cuò)誤。處理方式分兩種第一種是直接用腳本批量把BMP轉(zhuǎn)成jpg并同步改名這個(gè)是常規(guī)操作第二種是給數(shù)據(jù)加載器注冊(cè)BMP解碼器但不建議因?yàn)槠渌A(yù)處理步驟可能會(huì)再踩坑。我一般直接轉(zhuǎn)jpg一步到位。5.2 ultralytics調(diào)用數(shù)據(jù)集的配置寫(xiě)法以YOLOv8為例數(shù)據(jù)配置文件是data.yaml核心就三塊內(nèi)容訓(xùn)練路徑、驗(yàn)證路徑、類(lèi)別列表。train: dataset/images/train val: dataset/images/val nc: 5 names: [Sc, In, PS, Pa, Cr]yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16path字段可以省略如果填了就寫(xiě)數(shù)據(jù)集的絕對(duì)路徑。train和val路徑最好是Images目錄的路徑模型會(huì)自動(dòng)去對(duì)應(yīng)的labels目錄找標(biāo)注文件。nc必須跟classes.txt里的類(lèi)別數(shù)一致names順序必須跟轉(zhuǎn)換腳本里的class_names完全一致。訓(xùn)練命令里比較關(guān)鍵的參數(shù)是imgsz帶鋼圖片原始是200×200左右而YOLOv8默認(rèn)推理輸入是640模型會(huì)把小圖resize上去缺陷目標(biāo)會(huì)顯得更小。如果按640去訓(xùn)小目標(biāo)被放大后特征變模糊訓(xùn)練效果反而不如用原圖尺寸訓(xùn)。我建議先用imgsz320試一輪對(duì)比loss曲線(xiàn)再?zèng)Q定。5.3 類(lèi)別不平衡的采樣策略帶鋼表面缺陷數(shù)據(jù)集里不同缺陷類(lèi)型出現(xiàn)的頻次往往不一致。比如氧化皮可能占了一半而壓痕等缺陷只有幾張。類(lèi)別不平衡會(huì)讓模型偏向于學(xué)高頻缺陷低頻缺陷漏檢率上升。常見(jiàn)的做法是給低頻類(lèi)別做過(guò)采樣也就是讓數(shù)據(jù)加載器重復(fù)讀取包含稀有類(lèi)別的圖片?;蛘吒?jiǎn)單的方式是調(diào)整loss函數(shù)里每個(gè)類(lèi)別的權(quán)重。YOLOv8在loss里沒(méi)有直接開(kāi)放類(lèi)別權(quán)重參數(shù)但可以通過(guò)數(shù)據(jù)集層面的重采樣解決把含稀有類(lèi)別的圖片在train列表里多寫(xiě)幾遍相當(dāng)于變相過(guò)采樣。6. 進(jìn)階用法訓(xùn)練之后做一次標(biāo)注質(zhì)量回驗(yàn)數(shù)據(jù)集能不能復(fù)用關(guān)鍵看兩件事標(biāo)簽有沒(méi)有錯(cuò)、框有沒(méi)有偏。訓(xùn)練一輪之后把你的驗(yàn)證集圖片喂回模型做推理然后把預(yù)測(cè)框和XML標(biāo)注框畫(huà)在同一張圖上對(duì)比這一步能立刻暴露標(biāo)注質(zhì)量問(wèn)題。我自己的習(xí)慣是寫(xiě)一個(gè)可視化對(duì)比腳本左邊畫(huà)標(biāo)注框右邊畫(huà)預(yù)測(cè)框用差異顏色區(qū)分然后把差異大的圖單獨(dú)挑出來(lái)人工確認(rèn)。這樣做一輪之后你會(huì)發(fā)現(xiàn)帶鋼表面缺陷檢測(cè)模型的mAP上去了不是因?yàn)槟P妥儚?qiáng)了而是因?yàn)闃?biāo)注噪聲被清掉了一部分。從那以后我每次拿到標(biāo)注數(shù)據(jù)集都強(qiáng)制走一遍這個(gè)回驗(yàn)流程先跑一批快速訓(xùn)練把預(yù)測(cè)結(jié)果跟GT做對(duì)比再去決定要不要擴(kuò)展數(shù)據(jù)或者調(diào)整標(biāo)注避免直接進(jìn)入正式訓(xùn)練才發(fā)現(xiàn)數(shù)據(jù)問(wèn)題的尷尬。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取