實(shí)戰(zhàn):從YOLOv5到Y(jié)OLOv10的選型與部署)
鋼材表面質(zhì)量把控這件事在很長(zhǎng)一段時(shí)間里都靠質(zhì)檢員肉眼盯。帶鋼在產(chǎn)線上以每分鐘幾百米的速度跑缺陷轉(zhuǎn)瞬即逝人盯久了必然疲勞漏檢幾乎無(wú)法避免。這也是基于深度學(xué)習(xí)的表面缺陷檢測(cè)這幾年在金屬加工行業(yè)里反復(fù)被討論的原因。而真正談到落地繞不開(kāi)的就是YOLO這一系列檢測(cè)算法——從YOLOv5到Y(jié)OLOv7、YOLOv8再到新出的YOLOv10同一個(gè)任務(wù)在不同的版本上跑性能和坑都大不一樣。這篇文章是我在鋼材表面缺陷檢測(cè)項(xiàng)目上從零到一的完整記錄數(shù)據(jù)集怎么準(zhǔn)備、YOLOv5怎么訓(xùn)練、同一份數(shù)據(jù)下YOLOv7/8/10到底誰(shuí)更強(qiáng)、部署到真實(shí)質(zhì)檢環(huán)節(jié)會(huì)遇到哪些實(shí)驗(yàn)室里想不到的問(wèn)題。適合準(zhǔn)備拿工業(yè)視覺(jué)課題練手的人也適合已經(jīng)在做質(zhì)檢系統(tǒng)但想換一套更可靠模型的工程師。1. 表面缺陷檢測(cè)為什么會(huì)選中目標(biāo)檢測(cè)這條路1.1 人工質(zhì)檢和傳統(tǒng)視覺(jué)的局限先聊產(chǎn)線現(xiàn)狀。鋼材表面質(zhì)檢的傳統(tǒng)方案一靠人眼二靠常規(guī)圖像處理。人眼的短板是客觀生理限制質(zhì)檢員盯著一塊勻速運(yùn)動(dòng)的帶鋼表面注意力最多維持二十來(lái)分鐘疲勞之后細(xì)小缺陷的漏檢率會(huì)肉眼可見(jiàn)地上升。更麻煩的是一條產(chǎn)線的質(zhì)檢位往往要求連續(xù)運(yùn)轉(zhuǎn)好幾個(gè)小時(shí)漏檢帶來(lái)的客訴和退貨成本遠(yuǎn)高于多招一個(gè)質(zhì)檢員的成本。傳統(tǒng)圖像處理閾值分割、邊緣提取、模板匹配在單一背景的樣品圖上很有說(shuō)服力但鋼材表面本身就不是干凈背景——有氧化色差、有油污殘留、有紋理起伏這些干擾在圖像上的表現(xiàn)和真實(shí)缺陷高度相似。規(guī)則只要定得稍微嚴(yán)一點(diǎn)誤檢率就飆升定得松一點(diǎn)漏檢又回來(lái)了。我見(jiàn)過(guò)有人用形態(tài)學(xué)運(yùn)算試圖把劃傷和紋理噪聲分開(kāi)現(xiàn)場(chǎng)一換鋼種整套參數(shù)立刻失效。1.2 缺陷的本質(zhì)是找框加分類的問(wèn)題把問(wèn)題抽象一下無(wú)論裂紋、夾雜還是劃傷在圖像里都是一個(gè)局部區(qū)域有位置、有大小、有類別屬性。這正好落在目標(biāo)檢測(cè)的模型輸出空間里——矩形框標(biāo)出位置分類頭給出缺陷類型。所以表面缺陷檢測(cè)天然適合目標(biāo)檢測(cè)架構(gòu)而不是圖像分類或語(yǔ)義分割。分類模型給不出位置信息沒(méi)法指導(dǎo)現(xiàn)場(chǎng)定位缺陷分割模型需要像素級(jí)標(biāo)注成本高到工業(yè)數(shù)據(jù)規(guī)模根本撐不起來(lái)。綜合精度、速度、標(biāo)注成本三者目標(biāo)檢測(cè)是那個(gè)最平衡的選擇。這也是我在這個(gè)項(xiàng)目里始終堅(jiān)持檢測(cè)路線而不是分割路線的原因。1.3 六類典型缺陷各自的脾氣鋼材表面缺陷數(shù)據(jù)集里最常出現(xiàn)的六個(gè)類別識(shí)別難度差異非常大我這里逐個(gè)說(shuō)一下它們的脾氣裂紋細(xì)密的龜裂紋理顏色接近背景邊界模糊模型最容易漏檢。夾雜點(diǎn)狀或短條狀的異物壓入對(duì)比度中等形狀不固定。斑塊大面積灰暗區(qū)域邊緣柔和極易和光照不均混淆。麻點(diǎn)密集的小凹坑典型的小目標(biāo)問(wèn)題。氧化鐵皮壓入深色不規(guī)則塊狀與背景差異明顯但形狀多變。劃傷細(xì)長(zhǎng)線條長(zhǎng)寬比很極端標(biāo)注框很容易把無(wú)關(guān)背景包進(jìn)去。這六類的共性是類內(nèi)差異大、類間差異小。同一個(gè)劃傷有的又深又長(zhǎng)有的淺得像一層水印不同類型的缺陷之間比如斑塊和氧化鐵皮壓入肉眼看起來(lái)都是深色塊。模型要在這種數(shù)據(jù)上把類別分開(kāi)不是單純堆參數(shù)就能解決的。1.4 為什么最終落在了YOLO家族工業(yè)實(shí)時(shí)性要求讓兩階段檢測(cè)器先提候選框再分類基本出局YOLO這類單階段算法用一次前向同時(shí)完成定位和分類在速度和精度之間取得了很好的平衡。而且YOLO系列版本迭代快、社區(qū)資料多、部署方案成熟從訓(xùn)練到導(dǎo)出再到嵌入式推理每個(gè)環(huán)節(jié)都有現(xiàn)成方案。對(duì)一個(gè)落地項(xiàng)目來(lái)說(shuō)這比理論上更優(yōu)但資料稀少的算法重要得多。2. 數(shù)據(jù)集準(zhǔn)備先給模型定好天花板2.1 公開(kāi)數(shù)據(jù)和現(xiàn)場(chǎng)數(shù)據(jù)怎么配合我做對(duì)比實(shí)驗(yàn)用的是公開(kāi)的冷軋帶鋼表面缺陷數(shù)據(jù)集六類缺陷每類約三百?gòu)垬颖景?:2切成訓(xùn)練集和驗(yàn)證集。公開(kāi)數(shù)據(jù)的好處是標(biāo)注規(guī)范、類別齊全適合做算法驗(yàn)證和版本橫向?qū)Ρ葔奶幨潜尘疤蓛艉驼鎸?shí)產(chǎn)線的光照、氧化色、油污環(huán)境存在差距。如果目標(biāo)是部署上線我的建議是公開(kāi)數(shù)據(jù)打底現(xiàn)場(chǎng)數(shù)據(jù)微調(diào)。先用公開(kāi)數(shù)據(jù)把模型的基本能力訓(xùn)出來(lái)再采集幾百?gòu)埇F(xiàn)場(chǎng)圖片做增量訓(xùn)練?,F(xiàn)場(chǎng)圖片哪怕只有兩三百?gòu)垖?duì)真實(shí)場(chǎng)景的適配效果也遠(yuǎn)超純公開(kāi)數(shù)據(jù)。沒(méi)有現(xiàn)場(chǎng)數(shù)據(jù)就直接上產(chǎn)線早晚會(huì)在某個(gè)鋼種切換的時(shí)刻遭遇大規(guī)模誤檢。2.2 標(biāo)注格式和目錄組織YOLO系列統(tǒng)一使用txt格式的標(biāo)注文件每個(gè)圖像對(duì)應(yīng)一個(gè)同名txt每一行代表一個(gè)目標(biāo)框內(nèi)容是類別id 歸一化中心x 歸一化中心y 歸一化寬 歸一化高。我整理了一個(gè)固定目錄結(jié)構(gòu)方便后續(xù)換模型時(shí)直接復(fù)用defect-dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── defect.yaml如果你手里的標(biāo)注是VOC的xml或者COCO的json需要先轉(zhuǎn)成YOLO格式。下面這個(gè)Python腳本是我一直在用的轉(zhuǎn)換輔助邏輯很簡(jiǎn)單讀取xml里的obj把xmin、ymin、xmax、ymax換算成歸一化的cx、cy、w、h寬高除以圖片寬高防止越界import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_dir, img_w, img_h, class_names): 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_names: continue cls_id class_names.index(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) cx ((xmin xmax) / 2) / img_w cy ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) name os.path.splitext(os.path.basename(xml_path))[0] with open(os.path.join(out_dir, name .txt), w) as f: f.write(\n.join(lines))有個(gè)細(xì)節(jié)很多人會(huì)忽略坐標(biāo)系和歸一化之前必須確認(rèn)圖片尺寸和標(biāo)注軟件里的尺寸一致。我遇到過(guò)標(biāo)注軟件自動(dòng)壓縮了預(yù)覽圖導(dǎo)出坐標(biāo)和原圖尺寸對(duì)不上訓(xùn)練時(shí)loss一直不降最后發(fā)現(xiàn)是標(biāo)注坐標(biāo)全偏了。2.3 數(shù)據(jù)增強(qiáng)里的一個(gè)關(guān)鍵取舍YOLO系列自帶一套挺強(qiáng)大的數(shù)據(jù)增強(qiáng)包括mosaic四圖拼接、mixup、HSV擾動(dòng)、隨機(jī)翻轉(zhuǎn)、隨機(jī)平移縮放。對(duì)缺陷檢測(cè)來(lái)說(shuō)mosaic對(duì)小目標(biāo)尤其有效它把小缺陷放大到整圖比例模型能學(xué)到更多上下文。但這里有個(gè)容易踩的坑mosaic在訓(xùn)練后期最好降權(quán)或關(guān)閉。因?yàn)閙osaic生成的是拼接圖真實(shí)產(chǎn)線圖片不會(huì)長(zhǎng)成這種四宮格樣子訓(xùn)練到后期模型的分布會(huì)被拼接圖帶偏在正常驗(yàn)證圖上反而發(fā)飄。我習(xí)慣把mosaic從1.0逐步降到0.3到0.5之間或者跑到一半epoch之后關(guān)掉。具體怎么設(shè)要看loss曲線遇到訓(xùn)練loss一直降、驗(yàn)證mAP卻不動(dòng)甚至往下掉先懷疑數(shù)據(jù)增強(qiáng)和真實(shí)分布的偏差。類別不平衡也得單獨(dú)處理。公開(kāi)數(shù)據(jù)里斑塊、裂紋樣本多麻點(diǎn)、氧化鐵皮壓入樣本少如果直接用原始分布訓(xùn)練少樣本類別的AP會(huì)很難看。最簡(jiǎn)單的解法是給少數(shù)類別多復(fù)制幾輪過(guò)采樣訓(xùn)練時(shí)人為拉平各類別樣本比例。我實(shí)測(cè)過(guò)光這一步就能讓麻點(diǎn)和氧化鐵皮壓入的AP提高5個(gè)點(diǎn)以上。3. YOLOv5實(shí)戰(zhàn)訓(xùn)練配置、參數(shù)和過(guò)程分析3.1 環(huán)境準(zhǔn)備和工程擺放YOLOv5的依賴非常輕核心就是PyTorch和它的一套配套庫(kù)。我用的環(huán)境大概是這樣Python 3.8、PyTorch 1.13、CUDA 11.7、單張顯卡顯存12G。跑s模型、640分辨率、batch 16完全沒(méi)壓力。數(shù)據(jù)配置文件defect.yaml是訓(xùn)練的第一步。文件內(nèi)容不長(zhǎng)但每個(gè)字段都有講究path: ./defect-dataset train: images/train val: images/val nc: 6 names: 0: crazing 1: inclusion 2: patches 3: pitted_surface 4: rolled-in_scale 5: scratchespath字段是數(shù)據(jù)集根目錄train和val是相對(duì)路徑。nc必須和names里的類別數(shù)一致。有個(gè)低級(jí)但常見(jiàn)的錯(cuò)誤names的索引順序和標(biāo)注txt里的類別id對(duì)不上結(jié)果模型把裂紋當(dāng)成了劃傷損失函數(shù)還以為自己在收斂。3.2 預(yù)訓(xùn)練權(quán)重、分辨率和訓(xùn)練參數(shù)訓(xùn)練命令我貼一下后面逐個(gè)參數(shù)解釋python train.py \ --data defect.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 150 \ --patience 30 \ --hyp data/hyps/hyp.scratch-low.yamlweights用yolov5s.pt而不是從頭訓(xùn)練。COCO預(yù)訓(xùn)練權(quán)重里已經(jīng)包含大量通用物體特征遷移到鋼材缺陷這種小樣本數(shù)據(jù)上收斂速度和最終精度都明顯更好。工業(yè)數(shù)據(jù)集通常只有幾千張從頭訓(xùn)純屬浪費(fèi)算力。img 640是訓(xùn)練分辨率。缺陷里很多是小目標(biāo)有條件可以試1280對(duì)小缺陷檢測(cè)有明顯幫助但顯存和推理耗時(shí)都會(huì)漲。我的建議是640起步先把整體流程跑通再?zèng)Q定要不要升分辨率。batch 16在顯存允許時(shí)盡量大。大batch能讓梯度的方向更穩(wěn)定訓(xùn)練曲線更平滑。epochs 150對(duì)不到兩千張圖的數(shù)據(jù)集來(lái)說(shuō)足夠了。我開(kāi)了早停patience 30如果連續(xù)30個(gè)epoch驗(yàn)證集mAP沒(méi)有提升就自動(dòng)停止能省掉無(wú)效訓(xùn)練時(shí)間。hyp選擇low版本因?yàn)殇摬娜毕輸?shù)據(jù)量小增強(qiáng)太猛容易把模型訓(xùn)壞。3.3 訓(xùn)練過(guò)程監(jiān)控的幾個(gè)觀察點(diǎn)訓(xùn)練開(kāi)始后不要盯著終端里的loss數(shù)字胡思亂想要看三樣?xùn)|西loss曲線、驗(yàn)證集mAP曲線、PR曲線。一個(gè)典型過(guò)程是這樣的前30個(gè)epoch訓(xùn)練loss快速下降驗(yàn)證集mAP從0直接爬到0.6附近這個(gè)階段模型在學(xué)大局特征到epoch 80左右loss降速變緩mAP在小范圍內(nèi)震蕩此時(shí)模型在打磨邊界細(xì)節(jié)。如果這個(gè)階段持續(xù)很久不漲大概率不是算力不夠而是數(shù)據(jù)問(wèn)題——我遇到過(guò)標(biāo)注邊界太松導(dǎo)致類別內(nèi)特征發(fā)散的情況。另外記得看每類的AP而不是只看mAP這個(gè)總指標(biāo)。我在YOLOv5s上的初步結(jié)果六類平均mAP0.5在0.75左右但單看裂紋只有0.55。如果不拆開(kāi)看類別根本不會(huì)知道是裂紋拖了后腿。3.4 遇到mAP怎么調(diào)都上不去怎么辦我最想強(qiáng)調(diào)的工作習(xí)慣是先查badcase再談?wù){(diào)參。把驗(yàn)證集里所有置信度在0.3到0.7之間的檢測(cè)框?qū)С龀蓤D片一張張過(guò)目至少要過(guò)一百?gòu)?。絕大多數(shù)時(shí)候你會(huì)發(fā)現(xiàn)模型犯錯(cuò)是有規(guī)律的裂紋被標(biāo)成背景麻點(diǎn)被一個(gè)更大的框錯(cuò)誤覆蓋斑塊和氧化鐵皮壓入被互相混認(rèn)。這些規(guī)律指向的是數(shù)據(jù)問(wèn)題而不是模型問(wèn)題——裂紋樣本的標(biāo)注邊界是不是太含糊麻點(diǎn)的框是不是經(jīng)常把兩個(gè)挨著的缺陷畫成一個(gè)我試過(guò)花了兩周調(diào)超參最后AP只漲了一個(gè)點(diǎn)而重新洗了一遍標(biāo)注之后裂紋AP直接漲了七八個(gè)點(diǎn)。這件事給我的教訓(xùn)是先把評(píng)估集搞干凈再動(dòng)模型。4. YOLOv7、YOLOv8、YOLOv10的橫向?qū)崪y(cè)與選型判斷4.1 三個(gè)版本各自的核心變化YOLOv7主打的是結(jié)構(gòu)設(shè)計(jì)和訓(xùn)練策略的改良E-ELAN結(jié)構(gòu)讓特征在不同層之間的流動(dòng)更充分重參數(shù)化卷積把訓(xùn)練期的復(fù)雜結(jié)構(gòu)在推理期折疊成單路卷積輔助訓(xùn)練頭的設(shè)計(jì)讓淺層也能學(xué)到更強(qiáng)的特征。整體思路是在保持推理速度的前提下把精度往上抬一截。YOLOv8則做了架構(gòu)上的大調(diào)整檢測(cè)頭從anchor-based改成anchor-free不再需要預(yù)先定義錨框每個(gè)位置直接回歸目標(biāo)框的四條邊主干里的C3模塊換成C2f模塊特征重用更充分檢測(cè)頭拆成分類和回歸兩個(gè)獨(dú)立分支并用DFL損失做邊界回歸。這些改動(dòng)讓它在小目標(biāo)和密集場(chǎng)景下更穩(wěn)。YOLOv10的核心訴求是端到端無(wú)痛推理它通過(guò)一對(duì)多和一對(duì)一聯(lián)合標(biāo)簽分配策略讓模型推理階段完全不需要NMS后處理同時(shí)用輕量化分類頭、空間通道解耦下采樣、秩引導(dǎo)塊設(shè)計(jì)把網(wǎng)絡(luò)瘦身。少掉NMS那一步延遲和省算力的效果非常實(shí)在。做個(gè)類比v7是在原有的發(fā)動(dòng)機(jī)結(jié)構(gòu)上做精細(xì)化調(diào)校v8是重新設(shè)計(jì)了點(diǎn)火和燃燒方式v10更激進(jìn)直接把變速箱摘了讓動(dòng)力系統(tǒng)直連車輪。4.2 同一份數(shù)據(jù)上的實(shí)測(cè)數(shù)據(jù)為了盡量公平我在完全相同的訓(xùn)練集、驗(yàn)證集、超參和訓(xùn)練策略下微調(diào)了這幾個(gè)模型輸入分辨率統(tǒng)一640訓(xùn)練150個(gè)epoch。表格里的數(shù)字是我某一次實(shí)驗(yàn)的記錄不同輪次會(huì)有波動(dòng)所以不要把它當(dāng)絕對(duì)標(biāo)準(zhǔn)看趨勢(shì)就好模型參數(shù)量(M)mAP0.5mAP0.5:0.95單張推理耗時(shí)(ms,同GPU)YOLOv5s7.20.750.4810.5YOLOv736.90.790.5213.2YOLOv8s11.20.780.518.8YOLOv10s16.50.760.506.1幾個(gè)穩(wěn)定結(jié)論YOLOv7在這個(gè)任務(wù)上精度最高代價(jià)是模型大、推理稍慢YOLOv8s在精度和速度之間比較均衡YOLOv10s推理最快省掉NMS的額外耗時(shí)精度沒(méi)有明顯崩盤但也不是最強(qiáng)。值得注意的是v10對(duì)裂紋這類紋理型缺陷的AP普遍比v8低一到兩個(gè)點(diǎn)可能和輕量化主干對(duì)紋理特征的提取能力下降有關(guān)。4.3 實(shí)際項(xiàng)目里怎么選版本我的選型建議按場(chǎng)景來(lái)分如果做的是教學(xué)演示、快速驗(yàn)證或者團(tuán)隊(duì)對(duì)某個(gè)框架最熟YOLOv5s仍然是非常好的起點(diǎn)資料多、坑少、周邊工具齊全。如果質(zhì)檢工位對(duì)誤檢率要求高、現(xiàn)場(chǎng)的干擾物多YOLOv7的精度優(yōu)勢(shì)值得你拿算力去換。算力確實(shí)貴一點(diǎn)但漏一個(gè)缺陷導(dǎo)致的賠償可能比一臺(tái)顯卡貴十倍。如果要做多路并發(fā)檢測(cè)比如一條產(chǎn)線同時(shí)掛著四路相機(jī)YOLOv10的低延遲、免NMS特性可以顯著降低算力成本。如果后續(xù)還想擴(kuò)展分割、姿態(tài)等任務(wù)選YOLOv8系列更順手整個(gè)家族的模型結(jié)構(gòu)和工具鏈?zhǔn)墙y(tǒng)一的。不要唯指標(biāo)論。我之前在某個(gè)工位測(cè)試時(shí)發(fā)現(xiàn)某些版本在庫(kù)里AP數(shù)據(jù)很漂亮但導(dǎo)出到特定推理框架后個(gè)別算子不受支持被迫改圖重訓(xùn)最后反而不如AP低零點(diǎn)幾個(gè)點(diǎn)的舊版本好部署。兼容性、生態(tài)成熟度、團(tuán)隊(duì)熟悉度在工業(yè)項(xiàng)目里的權(quán)重比那1%的mAP差距高得多。5. 部署與落地模型跑起來(lái)只是開(kāi)始5.1 ONNX與TensorRT導(dǎo)出訓(xùn)練完只是第一步產(chǎn)線上跑的是經(jīng)過(guò)格式轉(zhuǎn)換的推理版本。通用流程是PyTorch權(quán)重先導(dǎo)出成ONNX再轉(zhuǎn)成TensorRT的engine格式做GPU加速。這么轉(zhuǎn)一圈推理耗時(shí)往往能再降三分之一以上特別是在TensorRT開(kāi)FP16之后。導(dǎo)出時(shí)有幾個(gè)參數(shù)要提前想清楚固定輸入尺寸還是動(dòng)態(tài)尺寸batch為1還是大于1。工業(yè)相機(jī)通常一次給一張圖固定尺寸、batch為1是最穩(wěn)妥的方案。千萬(wàn)不要圖省事直接開(kāi)動(dòng)態(tài)尺寸個(gè)別算子會(huì)因?yàn)閟hape不確定而被迫退回慢速路徑加速效果大打折扣。另外導(dǎo)出后務(wù)必用同一張圖對(duì)比PyTorch原模型和導(dǎo)出版本的輸出確認(rèn)框坐標(biāo)和類別沒(méi)有漂移。數(shù)值精度上FP16可能讓置信度偏百分之零點(diǎn)幾但如果框的位置變了說(shuō)明某個(gè)算子被錯(cuò)誤替換這時(shí)候要回頭更新推理框架版本。5.2 現(xiàn)場(chǎng)誤檢的來(lái)源和兜底手段實(shí)驗(yàn)室里再漂亮的指標(biāo)到產(chǎn)線上都要重新面對(duì)現(xiàn)實(shí)污染。我總結(jié)過(guò)真實(shí)場(chǎng)景誤檢的幾大來(lái)源光照隨車間時(shí)段變化、不同鋼種表面氧化程度不同、相機(jī)鏡頭有灰塵和反光、鋼板上有水漬油漬殘留、質(zhì)檢員在板上留了記號(hào)筆痕。應(yīng)對(duì)手段通常分四個(gè)層次采集現(xiàn)場(chǎng)負(fù)樣本把常見(jiàn)干擾物單獨(dú)處理或作為純背景圖片混入訓(xùn)練集參與負(fù)樣本學(xué)習(xí)在推理端適當(dāng)拉高置信度閾值寧可不報(bào)也不要每張圖亂報(bào)對(duì)同一物理位置的連續(xù)多幀輸出做時(shí)間維度的投票只有連續(xù)N幀都檢出同一個(gè)位置的缺陷才對(duì)外報(bào)警能濾掉大部分偶發(fā)誤檢在上位機(jī)做規(guī)則約束比如缺陷面積小到不構(gòu)成質(zhì)量影響、距帶鋼邊緣太近就不報(bào)警這些規(guī)則很適合過(guò)濾掉相機(jī)反光造成的邊界誤判。5.3 相機(jī)、光源與整個(gè)系統(tǒng)的延遲預(yù)算這其實(shí)是容易被算法工程師忽略的部分。鋼材產(chǎn)線的帶鋼運(yùn)動(dòng)速度、檢測(cè)幅寬、缺陷允許的最小尺寸共同決定了系統(tǒng)的幀率和延遲預(yù)算。舉個(gè)例子如果帶鋼速度是3米每秒檢測(cè)幅寬1米相機(jī)分辨率決定最小可檢缺陷尺寸那么相機(jī)觸發(fā)頻率、曝光時(shí)間、模型推理時(shí)間、結(jié)果回傳PLC的時(shí)間加起來(lái)必須控制在一個(gè)運(yùn)動(dòng)周期以內(nèi)否則缺陷即使被檢測(cè)到到達(dá)執(zhí)行機(jī)構(gòu)時(shí)也已經(jīng)跑過(guò)了報(bào)警位置。光源的選擇同樣關(guān)鍵明場(chǎng)照明適合找劃傷和麻點(diǎn)這類有方向性的缺陷暗場(chǎng)或低角度光源適合突顯壓入的氧化鐵皮。很多項(xiàng)目最后模型精度高但現(xiàn)場(chǎng)效果差問(wèn)題不在模型而在圖像采集那一端。5.4 讓模型持續(xù)進(jìn)化的回流閉環(huán)模型部署上線不是終點(diǎn)。我的做法是建立一套臟數(shù)據(jù)回流機(jī)制每?jī)芍苁占淮维F(xiàn)場(chǎng)的誤檢和漏檢圖片人工復(fù)核后補(bǔ)充進(jìn)訓(xùn)練集和驗(yàn)證集做一輪增量訓(xùn)練再替換線上模型。鋼材質(zhì)檢的特點(diǎn)就是鋼種和工藝會(huì)變?nèi)毕莘植家哺兡P捅仨毘掷m(xù)適配否則上線三個(gè)月之后精度就會(huì)悄悄滑坡。順便說(shuō)一個(gè)部署工程師常踩的坑評(píng)估新模型時(shí)直接拿新圖片和舊模型的輸出做對(duì)比而不去復(fù)盤新模型為什么變了。有時(shí)候新模型改了置信度分布把所有框的分?jǐn)?shù)整體壓低導(dǎo)致報(bào)警策略的閾值失效。這種情況要先對(duì)齊置信度分布再去比對(duì)檢測(cè)效果否則會(huì)被正常的分布偏移當(dāng)成故障來(lái)排查。6. 復(fù)盤這次折騰下來(lái)最想保留的幾個(gè)習(xí)慣第一永遠(yuǎn)先把評(píng)估集整理干凈。不管是公開(kāi)數(shù)據(jù)還是現(xiàn)場(chǎng)數(shù)據(jù)標(biāo)注質(zhì)量決定了模型能力的天花板模型結(jié)構(gòu)和超參只是決定在天花板底下能飛多高。第二一切結(jié)論都要落到每類AP和badcase上。總mAP會(huì)騙人單類AP不會(huì)。裂紋、麻點(diǎn)這類難例的AP比綜合指標(biāo)更能反映模型能不能上產(chǎn)線。第三選型時(shí)要把部署鏈路當(dāng)一個(gè)整體來(lái)評(píng)估。同是YOLO家族v5、v7、v8、v10的導(dǎo)出兼容性和周邊生態(tài)完全不同選型不是選模型是選一整套從數(shù)據(jù)到部署的方案。第四建立持續(xù)迭代的機(jī)制比任何一次訓(xùn)練都重要。現(xiàn)場(chǎng)數(shù)據(jù)會(huì)變模型必須跟著變?cè)O(shè)計(jì)好回流和重訓(xùn)的節(jié)奏系統(tǒng)才真正能用。我最后想說(shuō)的是鋼材表面缺陷檢測(cè)這個(gè)任務(wù)模型本身只占整個(gè)項(xiàng)目的一小半工作量。前期數(shù)據(jù)、中期選型、后期部署每一環(huán)都是在為模型的可落地性打工。如果你正在做類似的項(xiàng)目別急著換更先進(jìn)的模型版本先把數(shù)據(jù)和評(píng)估流程做扎實(shí)回報(bào)會(huì)比想象中大得多。