實(shí)戰(zhàn):從PVEL-AD數(shù)據(jù)集到模型部署)
光伏EL電致發(fā)光檢測(cè)是組件出廠前繞不開的一道硬門檻。通電后的電池片會(huì)在近紅外波段發(fā)出特定波長的光缺陷區(qū)域和正常區(qū)域在亮度、紋理上有明顯差異但因?yàn)檎姵孛娣e大、缺陷形態(tài)雜、背景干擾多純?nèi)斯づ袌D既累又容易漏檢。更重要的是想訓(xùn)練一套能真正上線的自動(dòng)檢測(cè)模型數(shù)據(jù)本身就繞不開一個(gè)關(guān)鍵點(diǎn)——缺陷不是一張圖像一個(gè)類別這么簡單而是多種缺陷形態(tài)在同一片電池上互相疊加。這也是我拿到PVEL-AD這套近紅外圖像數(shù)據(jù)集之后決定把YOLOv8訓(xùn)練流程完整梳理一遍的原因。PVEL-AD數(shù)據(jù)集主要覆蓋光伏電池EL成像下的內(nèi)部缺陷和異構(gòu)背景場(chǎng)景缺陷類別包括裂紋線狀和星狀、斷柵、黑芯、未對(duì)準(zhǔn)、粗線、劃痕、碎片、斷角和材料缺陷。簡單說它很適合用來驗(yàn)證檢測(cè)算法在缺陷形態(tài)差異極大、背景不統(tǒng)一條件下的表現(xiàn)。這篇文章不是貼一份官方文檔而是把從數(shù)據(jù)整理、標(biāo)注轉(zhuǎn)換、模型選型、訓(xùn)練調(diào)優(yōu)到部署推理的完整鏈路講清楚包括我踩過的坑和反復(fù)實(shí)驗(yàn)后覺得有效的做法。想用YOLOv8做光伏EL檢測(cè)的工程師、相關(guān)專業(yè)的研究生或者正在做工業(yè)缺陷檢測(cè)遷移學(xué)習(xí)的朋友這篇應(yīng)該能幫你少走不少彎路。1. 為什么光伏EL圖像缺陷檢測(cè)如此棘手——從PVEL-AD數(shù)據(jù)集說起1.1 近紅外成像下的缺陷表現(xiàn)形式先講點(diǎn)基礎(chǔ)。太陽能電池片在正向偏壓下會(huì)發(fā)出微弱紅外光正常區(qū)域亮度均勻缺陷區(qū)域因?yàn)閺?fù)合中心增多或結(jié)構(gòu)損傷導(dǎo)致發(fā)光強(qiáng)度下降所以呈現(xiàn)為暗斑、暗線或局部區(qū)域亮度異常。近紅外相機(jī)拍出來的本質(zhì)是單通道灰度圖很多人一上來就把它當(dāng)普通灰度圖處理實(shí)際上它的信噪比和自然圖像差很多背景還經(jīng)常有載臺(tái)反光、電極壓痕、邊緣遮擋等問題。PVEL-AD這類數(shù)據(jù)集的內(nèi)部缺陷指的就是這類只能在EL圖像中觀察到的隱性損傷表面肉眼往往看不出問題。不同缺陷形態(tài)差異極大我把常見的類別整理成了下表缺陷類別常見視覺特征檢測(cè)難點(diǎn)線狀裂紋細(xì)長暗線可能跨越大片區(qū)域長寬比極端目標(biāo)占比大但語義面積小星狀裂紋中心點(diǎn)向四周放射的暗紋中心區(qū)域小目標(biāo)密集邊緣與背景易混斷柵柵線局部缺失、連續(xù)暗線斷開細(xì)線目標(biāo)對(duì)分辨率要求高黑芯電池片中央大面積暗區(qū)與正常亮度分布不均易混淆未對(duì)準(zhǔn)圖形偏移、柵線重疊錯(cuò)位輪廓偏移而非單純強(qiáng)度變化粗線柵線寬度異常與正常柵線寬度差異需要量化判斷劃痕短促條紋狀暗紋與線狀裂紋相似類別之間容易混淆碎片邊緣碎裂、崩缺邊界目標(biāo)形狀不規(guī)則材料缺陷區(qū)域亮度異常、紋理不均晶界、位錯(cuò)帶來復(fù)雜暗紋這張表想說明一個(gè)道理光伏EL檢測(cè)不是找出亮暗異常這么粗糙線狀裂紋和星狀裂紋同樣是裂紋形態(tài)邏輯完全不同斷柵和粗線都涉及柵線但一個(gè)是缺失一個(gè)是增寬。模型要同時(shí)學(xué)這么多形態(tài)數(shù)據(jù)質(zhì)量和訓(xùn)練策略稍有問題某個(gè)類別就會(huì)直接塌掉。1.2 異構(gòu)背景到底帶來了什么麻煩所謂異構(gòu)背景簡單說就是不同圖像的背景長得很不一樣。從PVEL-AD這類數(shù)據(jù)來看有的圖電池片只占畫面70%有的占了95%有的圖帶了夾具邊緣有的圖的近紅外光源衰減導(dǎo)致明顯明暗梯度甚至不同產(chǎn)線、不同相機(jī)參數(shù)拍出來的背景紋理都不一樣。如果模型只見過單一背景上線后換一個(gè)拍攝環(huán)境立刻掉點(diǎn)。我處理異構(gòu)背景一般分三步第一步裁掉無效背景區(qū)域讓電池片主體盡量居中第二步做光照歸一化比如按圖像灰度均值做減法或者用限制對(duì)比度拉伸第三步在訓(xùn)練時(shí)加入隨機(jī)的亮度擾動(dòng)、隨機(jī)裁切位置擾動(dòng)讓模型不能靠背景猜缺陷位置。還有一個(gè)小細(xì)節(jié)容易被忽略很多EL圖像四周有黑色死邊如果標(biāo)注框沒覆蓋到模型大概率會(huì)把靠近死邊當(dāng)成某種特征。所以在數(shù)據(jù)清洗階段我會(huì)專門看邊緣區(qū)域把包含夾具、死邊、異常反光的圖片單獨(dú)建一個(gè)集合反復(fù)檢查避免模型學(xué)到邊界缺陷的偽規(guī)則。2. 訓(xùn)練前的數(shù)據(jù)準(zhǔn)備標(biāo)注格式轉(zhuǎn)換、圖像切片與增強(qiáng)策略2.1 從公開標(biāo)注格式到Y(jié)OLOv8的txt標(biāo)注YOLOv8使用的ultralytics庫要求數(shù)據(jù)集按固定目錄組織原始標(biāo)注通常不是這個(gè)格式所以第一步一定是格式轉(zhuǎn)換。我常用的目錄結(jié)構(gòu)如下dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml如果PVEL-AD的原始標(biāo)注是COCO JSON格式我會(huì)寫一個(gè)腳本把它轉(zhuǎn)成YOLO的txt格式。核心邏輯是讀取每張圖像的寬高然后把每個(gè)標(biāo)注框的絕對(duì)坐標(biāo)轉(zhuǎn)換成歸一化的中心點(diǎn)坐標(biāo)和寬高import json import os def convert_coco_json_to_yolo(coco_json_path, output_label_dir): with open(coco_json_path, r) as f: data json.load(f) categories {cat[id]: idx for idx, cat in enumerate(data[categories])} os.makedirs(output_label_dir, exist_okTrue) for img in data[images]: img_w, img_h img[width], img[height] lines [] for ann in data[annotations]: if ann[image_id] ! img[id]: continue bbox ann[bbox] x, y, w, h bbox cx x w / 2 cy y h / 2 category_id categories[ann[category_id]] lines.append( f{category_id} {cx/img_w:.6f} {cy/img_h:.6f} {w/img_w:.6f} {h/img_h:.6f} ) out_path os.path.join( output_label_dir, img[file_name].replace(.png, .txt).replace(.jpg, .txt) ) with open(out_path, w) as wf: wf.write(\n.join(lines))這里必須強(qiáng)調(diào)千萬不要直接把COCO格式的絕對(duì)坐標(biāo)塞進(jìn)YOLO標(biāo)注。YOLO格式要求中心點(diǎn)x、y和寬高width、height都除以圖像寬高歸一化到0到1之間。我見過很多新手在這步翻車訓(xùn)練時(shí)loss看起來正常但預(yù)測(cè)框全偏到角落排查起來特別費(fèi)勁。原因很簡單——坐標(biāo)沒有歸一化模型學(xué)到的框位置關(guān)系就是錯(cuò)的。建議轉(zhuǎn)換后用可視化腳本把標(biāo)注框畫出來逐張抽查不要嫌麻煩。data.yaml也要和轉(zhuǎn)換腳本的類別順序嚴(yán)格一致path: ./dataset train: images/train val: images/val nc: 10 names: 0: crack_line 1: crack_star 2: finger_interruption 3: black_core 4: misalignment 5: thick_line 6: scratch 7: fragment 8: corner_break 9: material_defect2.2 EL圖像的增強(qiáng)策略要克制說到數(shù)據(jù)增強(qiáng)很多剛從自然圖像檢測(cè)轉(zhuǎn)到工業(yè)檢測(cè)的人會(huì)犯一個(gè)錯(cuò)誤把YOLOv8默認(rèn)的增強(qiáng)參數(shù)直接拉滿結(jié)果訓(xùn)練出來的模型在驗(yàn)證集上還行一到真實(shí)數(shù)據(jù)上就各種亂檢。原因很簡單——EL圖像和自然圖像的性質(zhì)完全不同很多常規(guī)增強(qiáng)手段對(duì)紅外灰度圖是有害的。以我的經(jīng)驗(yàn)EL圖像的增強(qiáng)策略應(yīng)該盡量克制。hsv色彩擾動(dòng)對(duì)紅外灰度圖意義不大因?yàn)橥ǖ辣旧硎菃紊炼刃畔?qiáng)行加hsv擾動(dòng)反而可能引入偽紋理上下翻轉(zhuǎn)是否開啟要慎重太陽能電池在流水線上方向固定柵線方向一般保持一致雖然模型理論上可以適應(yīng)翻轉(zhuǎn)但會(huì)浪費(fèi)一部分容量。左右翻轉(zhuǎn)則通常可用因?yàn)槿毕荼旧碓谧笥曳较蛏蠜]有物理約束。下面是一組我在類似EL數(shù)據(jù)集上實(shí)測(cè)下來比較穩(wěn)的參數(shù)供參考輸入分辨率640起步后續(xù)根據(jù)缺陷大小再試1280hsv_h0.0hsv_s0.0hsv_v0.1fliplr0.5flipud0.0mosaic0.5mixup0.1還有一類問題是EL原圖往往非常大常見的有3200x3200甚至更大直接resize到640會(huì)丟失細(xì)小裂紋的細(xì)節(jié)。更實(shí)際的做法是滑窗切片把大圖切成若干1024x1024的塊再喂給YOLOv8訓(xùn)練。切片時(shí)相鄰block之間要留一定重疊度推理時(shí)再把框映射回原圖坐標(biāo)用NMS聚合重疊區(qū)域的檢測(cè)結(jié)果。我自己的感受是切片操作對(duì)線狀裂紋和斷柵的召回率提升非常明顯代價(jià)是訓(xùn)練和推理時(shí)間成倍增加。3. YOLOv8模型選型與訓(xùn)練策略先跑通再談?wù){(diào)優(yōu)3.1 模型變體選型n/s/m/l/x如何選YOLOv8從n到x參數(shù)量和推理延遲依次增加。工業(yè)缺陷檢測(cè)場(chǎng)景我很少一開始就上最大的x模型因?yàn)镋L缺陷數(shù)據(jù)量通常有限大模型非常容易過擬合。通用路線是先拿yolov8n或yolov8s跑通整個(gè)流程確認(rèn)數(shù)據(jù)處理鏈路沒有問題再換yolov8m做精度提升。如果目標(biāo)是產(chǎn)線實(shí)時(shí)檢測(cè)通常會(huì)選yolov8s或yolov8n導(dǎo)出部署同時(shí)配合高分辨率輸入。分辨率方面線狀裂紋長寬比可以到幾十比一斷柵又細(xì)又短640分辨率經(jīng)常不夠用。EL圖像缺陷對(duì)比度低小目標(biāo)在resize之后可能只剩一兩個(gè)像素模型根本沒法學(xué)。我實(shí)測(cè)下來把輸入分辨率從640提到1280線狀裂紋和星狀裂紋的召回率往往能提升超過10個(gè)百分點(diǎn)。當(dāng)然代價(jià)是顯存和訓(xùn)練時(shí)間上漲需要自己權(quán)衡。3.2 預(yù)訓(xùn)練權(quán)重、學(xué)習(xí)率和訓(xùn)練輪數(shù)的設(shè)置環(huán)境安裝這一步很簡單pip install ultralytics訓(xùn)練前先引入預(yù)訓(xùn)練權(quán)重一般用yolov8n.pt作為初始權(quán)重。COCO預(yù)訓(xùn)練權(quán)重可以讓淺層特征更快收斂不要完全隨機(jī)初始化工業(yè)場(chǎng)景數(shù)據(jù)量本來就少預(yù)訓(xùn)練遷移的價(jià)值非常大。一條可參考的訓(xùn)練命令是這樣的yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ workers8 \ device0 \ patience20學(xué)習(xí)率方面ultralytics默認(rèn)lr00.01如果batch比較大學(xué)習(xí)率可以適當(dāng)提高到0.005到0.01之間具體要看訓(xùn)練曲線。設(shè)置patience20是為了早停避免在過擬合階段白白浪費(fèi)時(shí)間。損失曲線和指標(biāo)不能只看訓(xùn)練集EL圖像類別不平衡嚴(yán)重訓(xùn)練loss低不代表難例檢測(cè)效果好關(guān)鍵要看驗(yàn)證集上的mAP和PR曲線。4. 訓(xùn)練過程監(jiān)控與失敗案例排查損失、mAP和過擬合4.1 按電池片劃分?jǐn)?shù)據(jù)避免同源泄漏這是我認(rèn)為最值得單獨(dú)拿出來說的一個(gè)點(diǎn)。很多人把EL大圖切片后直接隨機(jī)劃分訓(xùn)練集和驗(yàn)證集同一個(gè)電池片的不同切片可能同時(shí)出現(xiàn)在兩邊。模型在訓(xùn)練時(shí)見過同一片電池的某個(gè)局部紋理驗(yàn)證時(shí)又碰到同一片電池的另一個(gè)局部整體特征高度相似驗(yàn)證集指標(biāo)會(huì)虛高得非??鋸垺N矣龅竭^真實(shí)案例隨機(jī)劃分時(shí)mAP50跑到了0.92按電池片分組重新劃分后掉到0.78。后者才是上線后真正能達(dá)到的水平。正確做法是先按電池片來源分組再按組劃分訓(xùn)練集和驗(yàn)證集。如果原始數(shù)據(jù)沒有明確的電池片ID至少要保證同一次拍攝、同一片電池的相鄰切片不跨集合。這個(gè)問題不解決后面所有調(diào)優(yōu)都是在錯(cuò)誤的評(píng)估基準(zhǔn)上進(jìn)行的。4.2 從訓(xùn)練日志和可視化結(jié)果判斷模型狀態(tài)訓(xùn)練過程中我會(huì)重點(diǎn)盯這幾個(gè)信號(hào)train/loss下降是否平穩(wěn)val/loss在哪個(gè)epoch開始回升precision和recall各自的變化趨勢(shì)。對(duì)缺陷檢測(cè)來說recall尤其敏感因?yàn)楫a(chǎn)線漏檢直接造成損失誤檢可以靠人工二次確認(rèn)兜底。如果訓(xùn)練結(jié)果是precision低而recall高說明模型把大量背景誤判成缺陷問題大概率出在背景干擾優(yōu)先回去檢查數(shù)據(jù)清洗和光照歸一化如果recall低而precision高說明缺陷本身沒有學(xué)夠優(yōu)先提高輸入分辨率、增加難例增強(qiáng)、檢查標(biāo)注質(zhì)量。還有一個(gè)非常常見的隱蔽問題loss正常下降但小缺陷完全檢測(cè)不出來。這時(shí)可以用模型在驗(yàn)證集上輸出幾張可視化圖把預(yù)測(cè)框和真實(shí)框畫到同一張圖上重點(diǎn)觀察星狀裂紋中心區(qū)域和線狀裂紋末端。很多時(shí)候問題出在標(biāo)注框太大——YOLO訓(xùn)練時(shí)框尺寸會(huì)影響正樣本分配如果裂紋標(biāo)注框過寬模型學(xué)到的是亮暗區(qū)域而丟失細(xì)節(jié)檢測(cè)框就會(huì)明顯偏大且定位不準(zhǔn)。5. 各類缺陷的檢測(cè)難點(diǎn)與針對(duì)性優(yōu)化5.1 線狀裂紋與星狀裂紋長寬比極端與密集小目標(biāo)線狀裂紋可以說是整個(gè)數(shù)據(jù)集里最考驗(yàn)?zāi)P偷念悇e。它可能只有幾十像素寬卻有幾百上千像素長某些場(chǎng)景下拉成一條斜線橫跨電池片。雖然YOLOv8不依賴傳統(tǒng)anchor框?qū)O端長寬比有一定容忍度但檢測(cè)框本質(zhì)上還是矩形框內(nèi)包含大量正常區(qū)域訓(xùn)練時(shí)正負(fù)樣本的邊界就比較模糊。我實(shí)測(cè)效果更好的做法有兩個(gè)一是切片讓裂紋形態(tài)在輸入圖像中相對(duì)完整且占比合理二是提高輸入分辨率讓細(xì)線有足夠的像素支撐。星狀裂紋則是另一類問題。中心區(qū)域的暗紋交織在一起密集的時(shí)候一張圖能有幾十個(gè)星狀缺陷用單框表達(dá)會(huì)產(chǎn)生大量重疊。如果NMS的IoU閾值設(shè)置偏高相鄰的星狀裂紋框會(huì)被合并直接漏檢。我的處理辦法是把NMS IoU閾值從默認(rèn)值適當(dāng)調(diào)低比如從0.7降到0.5讓重疊的框保留更多候選同時(shí)在標(biāo)注層面把星狀裂紋當(dāng)做一個(gè)整體語義區(qū)域來標(biāo)框而不是把每一條放射紋都單獨(dú)標(biāo)一個(gè)框。5.2 斷柵、黑芯、未對(duì)準(zhǔn)等低頻缺陷的處理這幾個(gè)類別普遍樣本量偏少而且各有各的難處。斷柵細(xì)、短需要高分辨率支撐黑芯是大面積暗區(qū)極易和光照不均勻混淆未對(duì)準(zhǔn)更像是幾何偏移導(dǎo)致柵線重疊錯(cuò)位局部亮度變化可能并不顯著碎片和斷角都在電池片邊緣形狀又多種多樣。針對(duì)低頻類別一個(gè)常見的錯(cuò)誤做法是簡單做復(fù)制粘貼增強(qiáng)——把某個(gè)斷柵樣本直接貼到正常圖上。這樣模型學(xué)到的多半是邊界明顯的暗塊這種偽特征一到真實(shí)圖像上就崩潰。如果確實(shí)要做一定要讓粘貼塊在邊緣過渡、亮度分布上和背景嵌合難度其實(shí)不低。我的建議更保守先靠樣本加權(quán)和合理的訓(xùn)練輪數(shù)把這幾個(gè)類別的召回拉起來再考慮增強(qiáng)。黑芯這個(gè)類別額外值得注意。如果產(chǎn)線上相機(jī)老化或光源衰減正常電池片的亮度分布也可能出現(xiàn)中心暗區(qū)和黑芯在視覺上高度相似。為了減少這類誤檢條件允許的情況下產(chǎn)線端最好先做亮度歸一化把圖像整體亮度分布統(tǒng)一到同一水平再進(jìn)入模型。未對(duì)準(zhǔn)這一類如果原始數(shù)據(jù)帶有整片偏移的標(biāo)簽我更傾向于先做圖像對(duì)齊再做檢測(cè)而不是硬讓模型自己學(xué)出偏移特征。6. 從模型到產(chǎn)線部署導(dǎo)出、推理加速與誤檢率控制6.1 模型導(dǎo)出與推理管線模型訓(xùn)練完成后要把權(quán)重導(dǎo)出成適合部署的格式。常用做法是先導(dǎo)ONNX再轉(zhuǎn)TensorRT引擎推理速度能提升一個(gè)量級(jí)。導(dǎo)出命令比較簡單yolo export modelbest.pt formatonnx imgsz640導(dǎo)出時(shí)需要注意一點(diǎn)imgsz要固定。動(dòng)態(tài)尺寸雖然在接口上靈活但推理延遲和顯存占用都不可控產(chǎn)線場(chǎng)景寧可固定分辨率讓部署更穩(wěn)定。還有一個(gè)容易踩坑的細(xì)節(jié)灰度圖輸入在推理端要和訓(xùn)練預(yù)處理保持一致。訓(xùn)練時(shí)用OpenCV讀取圖像默認(rèn)是BGR三通道有的人會(huì)在數(shù)據(jù)處理階段把它轉(zhuǎn)成RGB如果導(dǎo)出后在另一個(gè)推理框架里用的是別的圖像加載庫通道順序沒對(duì)齊模型可能什么都檢不出來。不要覺得這是低級(jí)問題我在實(shí)際項(xiàng)目里遇到過一次排查了兩天才發(fā)現(xiàn)是BGR和RGB反了所有預(yù)測(cè)結(jié)果全都失真。超大圖切片推理是產(chǎn)線場(chǎng)景繞不開的。具體流程大圖先按固定尺寸切片每張切片獨(dú)立推理再把所有框映射回原圖坐標(biāo)重疊位置用加權(quán)NMS合并。切片之間的重疊度至少要留20%到30%否則跨切片的線狀裂紋會(huì)被截?cái)喑蓛山啬P涂赡軆蓚€(gè)半段都檢不出來。6.2 誤檢與漏檢的權(quán)衡以及上線后的持續(xù)迭代產(chǎn)線部署不能只看mAP。我會(huì)把模型效果拆成兩個(gè)維度看漏檢率即缺陷未檢出的比例過殺率即正常電池片被誤報(bào)成缺陷的比例。通過調(diào)整confidence閾值可以在這兩個(gè)指標(biāo)之間滑動(dòng)——閾值調(diào)低漏檢率下降但過殺率上升閾值調(diào)高則相反。上線前一定要和工藝側(cè)對(duì)齊明確哪些類別的誤檢可以被人工二次確認(rèn)兜住再據(jù)此定閾值。EL相機(jī)老化、光源衰減、電池片規(guī)格切換都會(huì)讓真實(shí)數(shù)據(jù)分布慢慢偏移。即使剛上線時(shí)模型效果很好過幾個(gè)月也可能因?yàn)閿?shù)據(jù)漂移開始大面積誤檢。我建議部署后保留一段時(shí)間的告警記錄定期抽檢模型在最新真實(shí)數(shù)據(jù)上的表現(xiàn)用最近積累的數(shù)據(jù)做增量訓(xùn)練而不是訓(xùn)練一次就一勞永逸。最后說一點(diǎn)個(gè)人體會(huì)。PVEL-AD這類EL數(shù)據(jù)集比普通自然圖像數(shù)據(jù)集難搞真正卡住項(xiàng)目的往往不是模型結(jié)構(gòu)而是數(shù)據(jù)劃分方式、背景歸一化、標(biāo)注一致性這些細(xì)枝末節(jié)。我現(xiàn)在的固定做法是每次實(shí)驗(yàn)前先把數(shù)據(jù)流和轉(zhuǎn)換腳本畫清楚把可視化檢查做成標(biāo)準(zhǔn)步驟寧可多花兩小時(shí)驗(yàn)證標(biāo)注也不要等訓(xùn)練結(jié)束后才發(fā)現(xiàn)源頭有問題。如果你在訓(xùn)練時(shí)遇到loss正常但上線效果差的情況先回去檢查背景再檢查數(shù)據(jù)劃分最后才考慮換模型。這套流程跑通之后后面新增缺陷類別、切換產(chǎn)線數(shù)據(jù)源其實(shí)都可以直接復(fù)用不用從頭再來。