據(jù)集:1800張帶標(biāo)簽圖像的工業(yè)質(zhì)檢應(yīng)用指南)
簡介這份鋼鐵表面缺陷檢測圖像數(shù)據(jù)集面向從事機(jī)器視覺與工業(yè)質(zhì)檢研究的開發(fā)者、學(xué)生及算法工程師用于訓(xùn)練和評估裂紋、銹蝕、凹坑、劃痕等表面缺陷的識別模型可作為課程實(shí)驗(yàn)、畢業(yè)設(shè)計(jì)或缺陷檢測算法對比的樣本來源。壓縮包為zip格式共約2000個(gè)文件主體是1800張jpg缺陷圖像并配有1400余個(gè)xml標(biāo)注文件與1400余個(gè)txt說明文件另有data、names等配置項(xiàng)整體約26.81MB體積輕便易于本地加載。數(shù)據(jù)集已按訓(xùn)練、驗(yàn)證、測試等劃分整理每張圖像均帶類別標(biāo)簽可直接用于監(jiān)督學(xué)習(xí)下的模型訓(xùn)練與精度、召回率、F1分?jǐn)?shù)等指標(biāo)驗(yàn)證省去自行標(biāo)注與切分的成本。目前已有2453人學(xué)習(xí)下載適合希望快速搭建缺陷檢測基線并復(fù)現(xiàn)實(shí)驗(yàn)的讀者參考使用。1. 鋼鐵表面缺陷檢測圖像數(shù)據(jù)集1800 張帶標(biāo)簽圖像到底能撐起什么產(chǎn)線上跑視覺檢測的同行大概都遇到過這種局面算法框架搭好了模型結(jié)構(gòu)也調(diào)通了卡住的卻是數(shù)據(jù)——要么樣本量不夠要么缺陷類別標(biāo)注得含糊要么圖像質(zhì)量跟現(xiàn)場相機(jī)對不上。鋼鐵表面缺陷檢測圖像數(shù)據(jù)集1800 張圖像含標(biāo)簽這類資源解決的正是這個(gè)冷啟動問題。它面向的是熱軋、冷軋帶鋼表面常見的夾雜、劃痕、麻點(diǎn)、氧化皮壓入等缺陷類型圖像帶分類或檢測標(biāo)簽適合做基線模型訓(xùn)練、數(shù)據(jù)增強(qiáng)策略驗(yàn)證、以及小樣本條件下的遷移學(xué)習(xí)實(shí)驗(yàn)。如果你正在做工業(yè)質(zhì)檢方向的算法預(yù)研或者要給一條新產(chǎn)線快速搭一個(gè)能跑起來的缺陷識別原型這個(gè)量級的數(shù)據(jù)集是夠用的起點(diǎn)但如果你指望直接拿它上線那得先看清它的邊界在哪。2. 1800 張鋼鐵缺陷圖像的數(shù)據(jù)結(jié)構(gòu)與標(biāo)簽體系怎么讀拿到一個(gè)圖像數(shù)據(jù)集第一件事不是急著喂模型而是把目錄結(jié)構(gòu)、標(biāo)簽格式、類別分布摸清楚。1800 張這個(gè)量級說大不大說小也不小——如果類別均衡、標(biāo)注質(zhì)量過關(guān)訓(xùn)練一個(gè)中等規(guī)模的分類網(wǎng)絡(luò)綽綽有余但如果長尾嚴(yán)重少數(shù)類可能只有幾十張直接訓(xùn)練必然翻車。所以這一章先把「怎么讀數(shù)據(jù)」講透再談怎么用。2.1 目錄結(jié)構(gòu)與標(biāo)簽文件的三種常見組織方式鋼鐵表面缺陷數(shù)據(jù)集常見的組織方式有三種按類別分文件夾class_name/*.jpg、圖像與標(biāo)注文件分離images/labels/、以及單文件 CSV/JSON 索引。前兩種在分類和檢測任務(wù)里最常見第三種多見于從標(biāo)注平臺導(dǎo)出的原始數(shù)據(jù)。不管你拿到的是哪種第一步都是寫個(gè)腳本把結(jié)構(gòu)打印出來別靠肉眼翻文件夾。import os from collections import Counter def inspect_dataset(root): 打印數(shù)據(jù)集目錄結(jié)構(gòu)與文件類型分布 ext_counter Counter() class_counter Counter() for dirpath, dirnames, filenames in os.walk(root): for f in filenames: ext os.path.splitext(f)[1].lower() ext_counter[ext] 1 # 假設(shè)按類別分文件夾取父目錄名作為類別 parent os.path.basename(dirpath) if ext in (.jpg, .jpeg, .png, .bmp): class_counter[parent] 1 print(文件擴(kuò)展名分布:, dict(ext_counter)) print(各類別圖像數(shù)量:, dict(class_counter)) return class_counter # 用法把 root 換成你的數(shù)據(jù)集根目錄 # inspect_dataset(./steel_defect_dataset)這段腳本做兩件事統(tǒng)計(jì)文件擴(kuò)展名確認(rèn)圖像格式是否統(tǒng)一鋼鐵數(shù)據(jù)集里常見 jpg 和 bmp 混用bmp 無損但體積大jpg 有壓縮偽影混用會影響模型對紋理的敏感度統(tǒng)計(jì)每個(gè)類別目錄下的圖像數(shù)量快速判斷類別均衡性。參數(shù)上沒什么可調(diào)的root指向數(shù)據(jù)集根目錄即可。跑完之后你會得到一張類別分布表如果發(fā)現(xiàn)某個(gè)類別少于 100 張后面訓(xùn)練時(shí)就得考慮過采樣或類別加權(quán)。2.2 類別分布統(tǒng)計(jì)與長尾問題的量化判斷1800 張圖像如果分 6 類平均每類 300 張聽起來還行但實(shí)際工業(yè)數(shù)據(jù)集往往不是均勻分布——正常樣本可能占一半某些罕見缺陷只有幾十張。長尾問題不量化就沒法決策所以得算兩個(gè)指標(biāo)最大類與最小類的比值不平衡比以及每類樣本數(shù)是否低于某個(gè)閾值。指標(biāo)計(jì)算方式判斷標(biāo)準(zhǔn)處理建議不平衡比最大類數(shù)量 / 最小類數(shù)量 10 視為嚴(yán)重長尾過采樣 類別加權(quán)損失最小類樣本數(shù)直接統(tǒng)計(jì) 100 張需警惕數(shù)據(jù)增強(qiáng)或遷移學(xué)習(xí)類別數(shù)標(biāo)簽去重610 類較常見過多則考慮合并細(xì)類我一般會先跑一遍統(tǒng)計(jì)把不平衡比算出來。如果比值在 3 以內(nèi)直接訓(xùn)練問題不大3 到 10 之間用加權(quán)交叉熵就能壓住超過 10光靠損失函數(shù)不夠得在數(shù)據(jù)層面做文章——對少數(shù)類做旋轉(zhuǎn)、翻轉(zhuǎn)、亮度擾動或者用切圖crop把大圖里的缺陷區(qū)域裁出來擴(kuò)充樣本。鋼鐵缺陷有個(gè)特點(diǎn)劃痕和夾雜在紋理上差異明顯但麻點(diǎn)和氧化皮壓入在低分辨率下容易混淆所以增強(qiáng)時(shí)別過度模糊否則類間邊界更糊。2.3 標(biāo)簽格式轉(zhuǎn)換從分類目錄到檢測標(biāo)注的落地路徑如果標(biāo)簽是按類別分文件夾給的那它天然適合分類任務(wù)但很多鋼鐵缺陷檢測場景需要的是邊界框這時(shí)候就得看數(shù)據(jù)集是否附帶檢測標(biāo)注如 VOC XML 或 YOLO txt。如果只有分類標(biāo)簽?zāi)阌袃蓷l路一是先做分類基線驗(yàn)證特征可分性二是用弱監(jiān)督或人工補(bǔ)標(biāo)的方式生成框標(biāo)注。常見做法是先用分類模型跑一遍看混淆矩陣再決定要不要投入標(biāo)注成本。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, img_w, img_h, class_map): 將 VOC 格式 XML 轉(zhuǎn)為 YOLO txt 格式 tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: continue cls_id class_map[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # YOLO 格式中心點(diǎn)坐標(biāo) 寬高均歸一化到 0~1 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 lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) return lines # class_map 示例{scratch: 0, inclusion: 1, pitted: 2}轉(zhuǎn)換邏輯不復(fù)雜但有兩個(gè)坑一是圖像尺寸必須和 XML 里記錄的一致如果數(shù)據(jù)集做過縮放而 XML 沒同步更新歸一化坐標(biāo)會全錯(cuò)二是類別名到 ID 的映射必須固定別在不同腳本里各寫一套否則訓(xùn)練時(shí)標(biāo)簽錯(cuò)位模型學(xué)出來的東西完全是玄學(xué)。參數(shù)上img_w和img_h建議直接從圖像文件讀取別硬編碼。3. 用這 1800 張圖訓(xùn)練缺陷分類基線從切分到首輪評估數(shù)據(jù)摸清楚了接下來就是跑一個(gè)能出數(shù)的基線。1800 張圖不算多別一上來就上大模型先用輕量網(wǎng)絡(luò)把流程跑通拿到混淆矩陣和每類 F1再決定往哪個(gè)方向加投入。這一章按「切分 → 訓(xùn)練 → 評估 → 看錯(cuò)例」的順序走每一步都給可復(fù)現(xiàn)的配置。3.1 訓(xùn)練集/驗(yàn)證集/測試集切分的分層策略圖像分類任務(wù)最常見的翻車點(diǎn)之一是切分不分層——隨機(jī)切完之后驗(yàn)證集里某個(gè)類別一張都沒有評估結(jié)果完全不可信。鋼鐵缺陷數(shù)據(jù)尤其要注意如果按文件夾隨機(jī)抽少數(shù)類很容易在驗(yàn)證集里消失。正確做法是按類別分層抽樣保證每個(gè)集合里各類別比例接近原始分布。import os import random import shutil from collections import defaultdict def stratified_split(root, out_root, ratios(0.7, 0.15, 0.15), seed42): 按類別分層切分?jǐn)?shù)據(jù)集為 train/val/test random.seed(seed) class_files defaultdict(list) for cls in os.listdir(root): cls_dir os.path.join(root, cls) if not os.path.isdir(cls_dir): continue for f in os.listdir(cls_dir): if f.lower().endswith((.jpg, .png, .bmp)): class_files[cls].append(os.path.join(cls_dir, f)) for cls, files in class_files.items(): random.shuffle(files) n len(files) n_train int(n * ratios[0]) n_val int(n * ratios[1]) splits { train: files[:n_train], val: files[n_train:n_train n_val], test: files[n_train n_val:] } for split, split_files in splits.items(): dst os.path.join(out_root, split, cls) os.makedirs(dst, exist_okTrue) for f in split_files: shutil.copy(f, dst) # stratified_split(./steel_defect_dataset, ./split_dataset)這段腳本的關(guān)鍵在defaultdict那一步先按類別把文件歸組再在組內(nèi)打亂切分保證每個(gè)集合都覆蓋所有類別。ratios默認(rèn) 7:1.5:1.51800 張圖對應(yīng)訓(xùn)練集約 1260 張、驗(yàn)證和測試各約 270 張。如果某個(gè)類別總數(shù)不到 20 張切完之后測試集可能只剩兩三張這時(shí)候建議把比例調(diào)成 8:1:1或者對少數(shù)類做留一法評估。seed固定住保證每次切分結(jié)果一致方便復(fù)現(xiàn)。3.2 輕量卷積網(wǎng)絡(luò)的首輪訓(xùn)練配置與關(guān)鍵超參基線模型我一般選 ResNet18 或 MobileNetV3-Small輸入尺寸 224×224batch size 32初始學(xué)習(xí)率 1e-3優(yōu)化器用 AdamW訓(xùn)練 30 個(gè) epoch 起步。鋼鐵缺陷的紋理特征比較細(xì)輸入尺寸別壓得太狠160×160 以下劃痕類缺陷容易丟細(xì)節(jié)。數(shù)據(jù)增強(qiáng)用隨機(jī)水平翻轉(zhuǎn)、±15 度旋轉(zhuǎn)、亮度對比度擾動別用太激進(jìn)的裁剪否則缺陷區(qū)域可能被裁掉。import torch import torch.nn as nn from torchvision import models, transforms # 數(shù)據(jù)增強(qiáng)與歸一化 train_tf transforms.Compose([ transforms.Resize((224, 224)), transforms.RandomHorizontalFlip(), transforms.RandomRotation(15), transforms.ColorJitter(brightness0.2, contrast0.2), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 加載預(yù)訓(xùn)練 ResNet18替換分類頭 model models.resnet18(weightsIMAGENET1K_V1) num_classes 6 # 按實(shí)際類別數(shù)修改 model.fc nn.Linear(model.fc.in_features, num_classes) # 類別加權(quán)損失緩解長尾 class_weights torch.tensor([1.0, 1.5, 2.0, 1.2, 3.0, 1.8]) # 按類別頻率反比設(shè)置 criterion nn.CrossEntropyLoss(weightclass_weights) optimizer torch.optim.AdamW(model.parameters(), lr1e-3, weight_decay1e-4)weightsIMAGENET1K_V1表示用 ImageNet 預(yù)訓(xùn)練權(quán)重初始化這在 1800 張的小數(shù)據(jù)集上是關(guān)鍵——從零訓(xùn)練幾乎必然過擬合。class_weights那行要按你實(shí)際的類別分布來調(diào)頻率越低的類權(quán)重越高但別超過 5否則少數(shù)類的梯度會主導(dǎo)更新把多數(shù)類的性能拉垮。學(xué)習(xí)率 1e-3 配合 AdamW 是比較穩(wěn)的起點(diǎn)如果 loss 在前幾個(gè) epoch 震蕩厲害降到 5e-4。3.3 混淆矩陣與每類 F1 的讀法判斷數(shù)據(jù)集能不能用訓(xùn)練跑完別只看總體準(zhǔn)確率。1800 張圖里如果正常樣本占一半模型全猜正常也能有 50% 準(zhǔn)確率這個(gè)數(shù)沒有意義。真正要看的是混淆矩陣和每類 F1。鋼鐵缺陷里最容易混的是麻點(diǎn)和氧化皮壓入——兩者在灰度圖上都表現(xiàn)為暗斑區(qū)別在邊緣銳度和分布密度。如果這兩類的混淆矩陣對角線很淡說明要么標(biāo)注邊界不清要么分辨率不夠這時(shí)候加數(shù)據(jù)不如先回頭查標(biāo)注一致性。評估指標(biāo)關(guān)注點(diǎn)異常信號每類召回率少數(shù)類是否被漏檢某類召回 0.5 需查樣本量每類精確率誤檢集中在哪兩類之間兩類互相混淆說明特征重疊宏平均 F1類別不均衡下的整體表現(xiàn)與準(zhǔn)確率差距大說明長尾嚴(yán)重我一般會把混淆矩陣畫出來盯著非對角線上的大數(shù)看。如果發(fā)現(xiàn)某兩類互相錯(cuò)得厲害先別急著調(diào)模型把錯(cuò)例圖調(diào)出來看幾張——很多時(shí)候是標(biāo)注本身就有歧義模型只是忠實(shí)地學(xué)了噪聲。4. 鋼鐵缺陷檢測的避坑清單五條血淚經(jīng)驗(yàn)這一章單獨(dú)拎出來講踩坑因?yàn)殇撹F表面缺陷這個(gè)場景有幾個(gè)特有的陷阱不提前說清楚后面調(diào)參調(diào)到頭禿也找不到原因。下面五條都是實(shí)際做下來反復(fù)遇到的按「現(xiàn)象 → 原因 → 解決」寫。4.1 圖像分辨率與現(xiàn)場相機(jī)不匹配導(dǎo)致指標(biāo)虛高現(xiàn)象離線訓(xùn)練集上 F1 跑到 0.92換到現(xiàn)場相機(jī)采的圖直接掉到 0.6。原因數(shù)據(jù)集里的圖像可能是經(jīng)過裁剪或縮放的分辨率和現(xiàn)場采集的不一致模型學(xué)到的紋理尺度對不上。解決訓(xùn)練前統(tǒng)一確認(rèn)圖像的實(shí)際物理分辨率每毫米像素?cái)?shù)如果現(xiàn)場相機(jī)參數(shù)不同在預(yù)處理里加一步重采樣把尺度對齊另外在驗(yàn)證集里混入少量現(xiàn)場圖做域適應(yīng)評估別只看公開集的數(shù)。4.2 標(biāo)簽噪聲同一類缺陷在不同圖像里標(biāo)注口徑不一致現(xiàn)象模型對某一類的預(yù)測忽好忽壞混淆矩陣?yán)镌擃惙稚⒌蕉鄠€(gè)類。原因標(biāo)注時(shí)對類別邊界定義不統(tǒng)一比如有的標(biāo)注者把淺劃痕歸到劃痕有的歸到麻點(diǎn)。解決抽 50 張圖人工復(fù)核統(tǒng)計(jì)類間歧義比例如果超過 10%要么合并細(xì)類要么重新制定標(biāo)注規(guī)范再補(bǔ)標(biāo)。鋼鐵缺陷的類別定義最好帶圖示說明光靠文字描述不同人理解差異很大。4.3 過度依賴亮度增強(qiáng)把缺陷特征抹掉現(xiàn)象加了 ColorJitter 之后驗(yàn)證集指標(biāo)反而降了。原因鋼鐵缺陷很多是靠灰度對比度區(qū)分的亮度擾動過大把弱缺陷的信號壓沒了。解決亮度擾動幅度控制在 ±0.1 以內(nèi)對比度擾動可以稍大但別和亮度同時(shí)拉滿更好的做法是用直方圖均衡化做預(yù)處理而不是在增強(qiáng)里隨機(jī)改亮度。4.4 小樣本類別直接過采樣導(dǎo)致過擬合現(xiàn)象少數(shù)類召回上去了但精確率崩了誤檢大量增加。原因簡單復(fù)制少數(shù)類樣本模型記住了具體圖像而不是特征。解決用過采樣時(shí)配合強(qiáng)增強(qiáng)旋轉(zhuǎn)、彈性變形或者改用 focal loss 讓模型聚焦難樣本更穩(wěn)的做法是先做遷移學(xué)習(xí)用預(yù)訓(xùn)練特征凍結(jié)前幾層只微調(diào)分類頭。4.5 訓(xùn)練/測試切分時(shí)同一張?jiān)瓐D的增強(qiáng)版本跨集泄漏現(xiàn)象測試集指標(biāo)好得不真實(shí)換一批新圖就露餡。原因先做數(shù)據(jù)增強(qiáng)再切分同一張?jiān)瓐D的不同增強(qiáng)版本同時(shí)出現(xiàn)在訓(xùn)練集和測試集。解決切分必須在增強(qiáng)之前做按原圖 ID 分組切分保證同一原圖的所有變體只落在一個(gè)集合里。這個(gè)坑在圖像分類里特別隱蔽因?yàn)樵鰪?qiáng)后的圖看起來不一樣但模型其實(shí)見過原圖。5. 從 1800 張到產(chǎn)線可用小樣本下的遷移與驗(yàn)證技巧1800 張圖做原型夠用但離產(chǎn)線還有距離。這一章講兩個(gè)進(jìn)階方向怎么用遷移學(xué)習(xí)把有限樣本的效用榨干以及怎么設(shè)計(jì)一套能說服自己的驗(yàn)證流程。最后給一個(gè)我常用的技巧——用「留出產(chǎn)線批次」做最終檢驗(yàn)而不是只看隨機(jī)切分的測試集。5.1 凍結(jié)策略與分層學(xué)習(xí)率的實(shí)操配置小數(shù)據(jù)集上微調(diào)預(yù)訓(xùn)練模型凍結(jié)多少層很關(guān)鍵。全凍結(jié)只訓(xùn)分類頭收斂快但特征適配不足全解凍又容易過擬合。我一般分三段前兩個(gè) stage 凍結(jié)第三個(gè) stage 和分類頭用較小學(xué)習(xí)率1e-4分類頭本身用 1e-3。這樣底層通用特征不動中層紋理特征小幅調(diào)整分類頭快速適配新類別。# 分層學(xué)習(xí)率凍結(jié)前兩層其余層用小學(xué)習(xí)率 for name, param in model.named_parameters(): if layer1 in name or layer2 in name: param.requires_grad False optimizer torch.optim.AdamW([ {params: [p for n, p in model.named_parameters() if fc in n], lr: 1e-3}, {params: [p for n, p in model.named_parameters() if fc not in n and p.requires_grad], lr: 1e-4} ], weight_decay1e-4)這段配置的核心是把分類頭和骨干網(wǎng)絡(luò)分開設(shè)學(xué)習(xí)率。requires_grad False凍掉前兩層減少可訓(xùn)練參數(shù)1800 張圖不至于把整個(gè)網(wǎng)絡(luò)帶偏。如果驗(yàn)證集指標(biāo)在 10 個(gè) epoch 內(nèi)不漲可以把 layer3 也解凍試試但學(xué)習(xí)率再降一檔。5.2 用留出批次驗(yàn)證代替隨機(jī)切分更接近產(chǎn)線的評估方式隨機(jī)切分的測試集有個(gè)問題同一批生產(chǎn)條件下拍的圖外觀高度相似隨機(jī)切分會讓訓(xùn)練集和測試集共享大量相似紋理指標(biāo)偏樂觀。更接近真實(shí)的做法是按采集批次留出——比如按時(shí)間段或鋼卷編號分組留出整批做測試。這樣能暴露模型對光照變化、批次間表面狀態(tài)差異的敏感度。具體操作是在切分腳本里加一個(gè)group_key參數(shù)按組切而不是按文件切。驗(yàn)證方式優(yōu)點(diǎn)局限適用階段隨機(jī)分層切分實(shí)現(xiàn)簡單類別均衡指標(biāo)偏樂觀基線快速驗(yàn)證按批次留出接近產(chǎn)線分布偏移需要批次元信息上線前評估跨域測試檢驗(yàn)泛化邊界需額外數(shù)據(jù)源模型選型對比5.3 一個(gè)習(xí)慣先看錯(cuò)例再調(diào)參最后說個(gè)我自己的習(xí)慣。每次指標(biāo)不達(dá)預(yù)期我第一件事不是改學(xué)習(xí)率或換模型而是把錯(cuò)例圖導(dǎo)出來看二十張。鋼鐵缺陷的錯(cuò)例往往能直接告訴你問題在哪——如果錯(cuò)例全是低對比度的麻點(diǎn)那是預(yù)處理對比度不夠如果錯(cuò)例集中在圖像邊緣那是切圖時(shí)缺陷被截?cái)嗳绻e(cuò)例的標(biāo)注框明顯偏了那是標(biāo)注質(zhì)量問題調(diào)模型純屬白費(fèi)功夫。這個(gè)習(xí)慣幫我省下的時(shí)間比任何調(diào)參技巧都多。數(shù)據(jù)量不大的時(shí)候人對錯(cuò)例的直覺比指標(biāo)更可靠。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取