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