工业视觉钢材缺陷检测 实战项目
质量是制造企业的核心竞争力之一,企业对产品质量的要求越来越高。但是,产品在制造过程中有时会出现表面缺陷,如何进行高效的质量控制来避免表面瑕疵产生,一直是制造企业面临的棘手问题之一。
传统主要通过人工抽检进行检测,由于抽检率低、实时性差,且受检测人员经验、疲劳状态等主观因素影响,往往检测结果稳定性不高,准确性无法保障,易出现瑕疵漏检等情况,难以适应高效的生产和质量要求。
随着数智技术发展,基于机器视觉的表面缺陷检测应用得以在实践中展开,大大提高了产线品控效率,避免了因作业条件、主观判断等因素影响检测结果的准确性和稳定性,在产品制造过程中,可以实现对每一环节、每一件产品表面缺陷的实时检测,更精确、快速的识别产品表面瑕疵缺陷,同时也节省了制造企业在质检环节的人工投入,降低了人力成本支出。目前在新能源、汽车、电子、包装、印刷、化工、食品、塑胶、纺织等制造领域广泛应用。
从零搭建一个基于深度学习的缺陷检测系统:通过喂给神经网络大量的历史缺陷数据集,进行模型训练,最终使用深度学习模型进行实时工业产品缺陷检测。
更多请查看:
工业缺陷检测场景简介
代码实战:YOLOv5实现钢材表面缺陷检测
针对钢材缺陷检测任务,将使用 Yolo V5 对数据集的图像进行检测。下载 Yolo V5 的 github 源码,配置好数据集。
源码地址:https://github.com/ultralytics/yolov5
YOLOv5 是 You Only Look Once (YOLO) 计算机视觉模型系列中的一个模型。YOLOv5 通常用于检测物体。YOLOv5 有四个主要版本:小型 (s)、中型 (m)、大型 (l) 和超大型 (x),每个版本都提供更高的准确率。每个变体也需要不同的时间来训练。
在上图中,您可以看到 YOLOv5 的所有变体训练速度都比 EfficientDet 快。最准确的 YOLOv5 模型 YOLOv5x 可以比 EfficientDet D4 模型以相似的准确度更快地处理图像。
YOLO 模型是第一个将边界框预测过程与端到端可微网络中的类标签连接起来的对象检测器。
YOLOv5 是从输入图像中创建特征,然后将这些特征输入预测系统,系统预测对象的位置,并在周围绘制框,并预测它们的类别。
YOLO 网络由三个主要部分组成。
关于 YOLO 更多内容可查看以下文章:
YOLOv4
YOLOv5
由东北大学(NEU)发布的表面缺陷数据库,收集了热轧钢带的六种典型表面缺陷,即轧制氧化皮(RS),斑块(Pa),开裂(Cr),点蚀表面( PS),内含物(In)和划痕(Sc)。该数据库包括1,800个灰度图像:六种不同类型的典型表面缺陷,每一类缺陷包含300个样本。
对于缺陷检测任务,数据集提供了注释,指示每个图像中缺陷的类别和位置。对于每个缺陷,黄色框是指示其位置的边框,绿色标签是类别分数。
数据集
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import os
from matplotlib import pyplot as plt
import cv2 as cv
train_image_path = '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/train/images'
valid_image_path = '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid/images'
train_dir = os.listdir(train_image_path)
valid_dir = os.listdir(valid_image_path)
print('训练集数量', len(train_dir))
print('测试集数量', len(valid_dir))
训练集数量 1740
测试集数量 60
标签情况:
[‘crazing’,
‘inclusion’,
‘patches’,
‘pitted_surface’,
‘rolled-in_scale’,
‘scratches’]
fig,ax = plt.subplots(1,4,figsize=(10,5))
image = cv.imread(os.path.join(valid_image_path,"crazing_10.jpg"))
ax[0].imshow(image)
image = cv.imread(os.path.join(valid_image_path,"inclusion_10.jpg"))
ax[1].imshow(image)
image = cv.imread(os.path.join(valid_image_path,"patches_10.jpg"))
ax[2].imshow(image)
image = cv.imread(os.path.join(valid_image_path,"scratches_10.jpg"))
ax[3].imshow(image)
fig.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gLji5tzU-1680494033696)(output_3_0.png)]
!ls
__notebook_source__.ipynb
# Download YOLOv5
!git clone https://github.com/ultralytics/yolov5 # clone repo
%cd yolov5
# Install dependencies
%pip install -qr requirements.txt # install dependencies
!ls
import torch
print(f"Setup complete. Using torch {torch.__version__} ({torch.cuda.get_device_properties(0).name if torch.cuda.is_available() else 'CPU'})")
Cloning into 'yolov5'...
remote: Enumerating objects: 15123, done.[K
remote: Counting objects: 100% (78/78), done.[K
remote: Compressing objects: 100% (66/66), done.[K
remote: Total 15123 (delta 42), reused 33 (delta 12), pack-reused 15045[K
Receiving objects: 100% (15123/15123), 14.19 MiB | 9.17 MiB/s, done.
Resolving deltas: 100% (10359/10359), done.
/kaggle/working/yolov5
[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
tensorflow-io 0.21.0 requires tensorflow-io-gcs-filesystem==0.21.0, which is not installed.
dask-cudf 21.10.1 requires cupy-cuda114, which is not installed.
beatrix-jupyterlab 3.1.7 requires google-cloud-bigquery-storage, which is not installed.
tensorflow 2.6.4 requires h5py~=3.1.0, but you have h5py 3.8.0 which is incompatible.
tensorflow 2.6.4 requires numpy~=1.19.2, but you have numpy 1.21.6 which is incompatible.
tensorflow 2.6.4 requires typing-extensions<3.11,>=3.7, but you have typing-extensions 4.1.1 which is incompatible.
tensorflow-transform 1.9.0 requires tensorflow!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,<2.10,>=1.15.5, but you have tensorflow 2.6.4 which is incompatible.
tensorflow-serving-api 2.9.0 requires tensorflow<3,>=2.9.0, but you have tensorflow 2.6.4 which is incompatible.
gcsfs 2022.5.0 requires fsspec==2022.5.0, but you have fsspec 2023.1.0 which is incompatible.
dask-cudf 21.10.1 requires dask==2021.09.1, but you have dask 2022.2.0 which is incompatible.
dask-cudf 21.10.1 requires distributed==2021.09.1, but you have distributed 2022.2.0 which is incompatible.[0m[31m
[0m[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv[0m[33m
[0mNote: you may need to restart the kernel to use updated packages.
CITATION.cff README.zh-CN.md detect.py requirements.txt tutorial.ipynb
CONTRIBUTING.md benchmarks.py export.py segment utils
LICENSE classify hubconf.py setup.cfg val.py
README.md data models train.py
Setup complete. Using torch 1.11.0 (Tesla P100-PCIE-16GB)
# Create .yaml file
import yaml
data_yaml = dict(
train = '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/train',
val = '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid',
nc = 6,
names = ['crazing', 'inclusion', 'patches', 'pitted_surface', 'rolled-in_scale', 'scratches']
)
# creating the file in the yolov5/data.yaml directory
with open('data.yaml', 'w') as outfile:
yaml.dump(data_yaml, outfile, default_flow_style=True)
!ls
CITATION.cff README.zh-CN.md data.yaml models train.py
CONTRIBUTING.md benchmarks.py detect.py requirements.txt tutorial.ipynb
LICENSE classify export.py segment utils
README.md data hubconf.py setup.cfg val.py
!wandb disabled
# -- img
!python train.py --img 640 --batch 16 --epochs 70 --data ./data.yaml --weights yolov5n.pt
W&B disabled.
[34m[1mwandb[0m: WARNING ⚠️ wandb is deprecated and will be removed in a future release. See supported integrations at https://github.com/ultralytics/yolov5#integrations.
[34m[1mtrain: [0mweights=yolov5n.pt, cfg=, data=./data.yaml, hyp=data/hyps/hyp.scratch-low.yaml, epochs=70, batch_size=16, imgsz=640, rect=False, resume=False, nosave=False, noval=False, noautoanchor=False, noplots=False, evolve=None, bucket=, cache=None, image_weights=False, device=, multi_scale=False, single_cls=False, optimizer=SGD, sync_bn=False, workers=8, project=runs/train, name=exp, exist_ok=False, quad=False, cos_lr=False, label_smoothing=0.0, patience=100, freeze=[0], save_period=-1, seed=0, local_rank=-1, entity=None, upload_dataset=False, bbox_interval=-1, artifact_alias=latest
[34m[1mgithub: [0mup to date with https://github.com/ultralytics/yolov5 ✅
YOLOv5 v7.0-97-gfa4bdbe Python-3.7.12 torch-1.11.0 CUDA:0 (Tesla P100-PCIE-16GB, 16281MiB)
[34m[1mhyperparameters: [0mlr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=0.05, cls=0.5, cls_pw=1.0, obj=1.0, obj_pw=1.0, iou_t=0.2, anchor_t=4.0, fl_gamma=0.0, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0
[34m[1mClearML: [0mrun 'pip install clearml' to automatically track, visualize and remotely train YOLOv5 in ClearML
[34m[1mComet: [0mrun 'pip install comet_ml' to automatically track and visualize YOLOv5 runs in Comet
[34m[1mTensorBoard: [0mStart with 'tensorboard --logdir runs/train', view at http://localhost:6006/
Downloading https://ultralytics.com/assets/Arial.ttf to /root/.config/Ultralytics/Arial.ttf...
100%|█████████████████████████████████████████| 755k/755k [00:00<00:00, 115MB/s]
Downloading https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5n.pt to yolov5n.pt...
100%|██████████████████████████████████████| 3.87M/3.87M [00:00<00:00, 19.4MB/s]
Overriding model.yaml nc=80 with nc=6
from n params module arguments
0 -1 1 1760 models.common.Conv [3, 16, 6, 2, 2]
1 -1 1 4672 models.common.Conv [16, 32, 3, 2]
2 -1 1 4800 models.common.C3 [32, 32, 1]
3 -1 1 18560 models.common.Conv [32, 64, 3, 2]
4 -1 2 29184 models.common.C3 [64, 64, 2]
5 -1 1 73984 models.common.Conv [64, 128, 3, 2]
6 -1 3 156928 models.common.C3 [128, 128, 3]
7 -1 1 295424 models.common.Conv [128, 256, 3, 2]
8 -1 1 296448 models.common.C3 [256, 256, 1]
9 -1 1 164608 models.common.SPPF [256, 256, 5]
10 -1 1 33024 models.common.Conv [256, 128, 1, 1]
11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
12 [-1, 6] 1 0 models.common.Concat [1]
13 -1 1 90880 models.common.C3 [256, 128, 1, False]
14 -1 1 8320 models.common.Conv [128, 64, 1, 1]
15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']
16 [-1, 4] 1 0 models.common.Concat [1]
17 -1 1 22912 models.common.C3 [128, 64, 1, False]
18 -1 1 36992 models.common.Conv [64, 64, 3, 2]
19 [-1, 14] 1 0 models.common.Concat [1]
20 -1 1 74496 models.common.C3 [128, 128, 1, False]
21 -1 1 147712 models.common.Conv [128, 128, 3, 2]
22 [-1, 10] 1 0 models.common.Concat [1]
23 -1 1 296448 models.common.C3 [256, 256, 1, False]
24 [17, 20, 23] 1 14883 models.yolo.Detect [6, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [64, 128, 256]]
Model summary: 214 layers, 1772035 parameters, 1772035 gradients, 4.2 GFLOPs
Transferred 343/349 items from yolov5n.pt
[34m[1mAMP: [0mchecks passed ✅
[34m[1moptimizer:[0m SGD(lr=0.01) with parameter groups 57 weight(decay=0.0), 60 weight(decay=0.0005), 60 bias
[34m[1malbumentations: [0mBlur(p=0.01, blur_limit=(3, 7)), MedianBlur(p=0.01, blur_limit=(3, 7)), ToGray(p=0.01), CLAHE(p=0.01, clip_limit=(1, 4.0), tile_grid_size=(8, 8))
[34m[1mtrain: [0mScanning /kaggle/input/neu-det-yolo/NEU-DET-YOLO/train/labels... 1740 ima[0m
[34m[1mtrain: [0mWARNING ⚠️ /kaggle/input/neu-det-yolo/NEU-DET-YOLO/train/images/crazing_120.jpg: 1 duplicate labels removed
[34m[1mtrain: [0mWARNING ⚠️ /kaggle/input/neu-det-yolo/NEU-DET-YOLO/train/images/inclusion_62.jpg: 1 duplicate labels removed
[34m[1mtrain: [0mWARNING ⚠️ /kaggle/input/neu-det-yolo/NEU-DET-YOLO/train/images/patches_198.jpg: 1 duplicate labels removed
[34m[1mtrain: [0mWARNING ⚠️ Cache directory /kaggle/input/neu-det-yolo/NEU-DET-YOLO/train is not writeable: [Errno 30] Read-only file system: '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/train/labels.cache.npy'
[34m[1mval: [0mScanning /kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid/labels... 60 images,[0m
[34m[1mval: [0mWARNING ⚠️ Cache directory /kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid is not writeable: [Errno 30] Read-only file system: '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid/labels.cache.npy'
[34m[1mAutoAnchor: [0m3.24 anchors/target, 0.989 Best Possible Recall (BPR). Current anchors are a good fit to dataset ✅
Plotting labels to runs/train/exp/labels.jpg...
Image sizes 640 train, 640 val
Using 2 dataloader workers
Logging results to [1mruns/train/exp[0m
Starting training for 70 epochs...
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
0/69 1.97G 0.09443 0.03959 0.05022 55 640: 1
Class Images Instances P R mAP50
all 60 124 0.00296 0.481 0.0128 0.00385
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
1/69 2.35G 0.06365 0.04147 0.03278 53 640: 1
Class Images Instances P R mAP50
all 60 124 0.289 0.184 0.155 0.0502
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
2/69 2.35G 0.05978 0.03654 0.01634 54 640: 1
Class Images Instances P R mAP50
all 60 124 0.623 0.115 0.106 0.0314
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
3/69 2.35G 0.05594 0.03582 0.009596 61 640: 1
Class Images Instances P R mAP50
all 60 124 0.354 0.183 0.137 0.0408
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
4/69 2.35G 0.05291 0.03502 0.008263 43 640: 1
Class Images Instances P R mAP50
all 60 124 0.519 0.248 0.196 0.0832
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
5/69 2.35G 0.0503 0.03501 0.007264 59 640: 1
Class Images Instances P R mAP50
all 60 124 0.53 0.489 0.446 0.171
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
6/69 2.35G 0.04788 0.03487 0.005603 64 640: 1
Class Images Instances P R mAP50
all 60 124 0.676 0.244 0.37 0.155
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
7/69 2.35G 0.04748 0.03407 0.004983 49 640: 1
Class Images Instances P R mAP50
all 60 124 0.389 0.463 0.436 0.166
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
8/69 2.35G 0.04573 0.03439 0.004757 42 640: 1
Class Images Instances P R mAP50
all 60 124 0.661 0.394 0.451 0.194
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
9/69 2.35G 0.04492 0.03452 0.005419 53 640: 1
Class Images Instances P R mAP50
all 60 124 0.664 0.227 0.32 0.153
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
10/69 2.35G 0.04409 0.03477 0.004775 44 640: 1
Class Images Instances P R mAP50
all 60 124 0.547 0.418 0.487 0.19
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
11/69 2.35G 0.04299 0.03376 0.004574 54 640: 1
Class Images Instances P R mAP50
all 60 124 0.601 0.464 0.519 0.227
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
12/69 2.35G 0.04276 0.03345 0.004303 53 640: 1
Class Images Instances P R mAP50
all 60 124 0.758 0.249 0.354 0.129
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
13/69 2.35G 0.04196 0.03305 0.00328 50 640: 1
Class Images Instances P R mAP50
all 60 124 0.543 0.619 0.634 0.313
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
14/69 2.35G 0.04184 0.03385 0.00348 44 640: 1
Class Images Instances P R mAP50
all 60 124 0.604 0.54 0.604 0.291
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
15/69 2.35G 0.04103 0.03317 0.003495 56 640: 1
Class Images Instances P R mAP50
all 60 124 0.516 0.5 0.577 0.255
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
16/69 2.35G 0.04057 0.03466 0.003991 47 640: 1
Class Images Instances P R mAP50
all 60 124 0.586 0.645 0.645 0.325
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
17/69 2.35G 0.04042 0.03322 0.003537 59 640: 1
Class Images Instances P R mAP50
all 60 124 0.431 0.488 0.431 0.209
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
18/69 2.35G 0.04006 0.03223 0.003051 44 640: 1
Class Images Instances P R mAP50
all 60 124 0.66 0.601 0.68 0.344
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
19/69 2.35G 0.04016 0.03271 0.003451 57 640: 1
Class Images Instances P R mAP50
all 60 124 0.764 0.563 0.689 0.369
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
20/69 2.35G 0.03986 0.03239 0.003499 40 640: 1
Class Images Instances P R mAP50
all 60 124 0.601 0.653 0.682 0.339
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
21/69 2.35G 0.0389 0.03197 0.002634 74 640: 1
Class Images Instances P R mAP50
all 60 124 0.609 0.634 0.679 0.33
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
22/69 2.35G 0.03842 0.03221 0.002661 62 640: 1
Class Images Instances P R mAP50
all 60 124 0.727 0.594 0.661 0.311
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
23/69 2.35G 0.03829 0.03186 0.002919 46 640: 1
Class Images Instances P R mAP50
all 60 124 0.672 0.618 0.675 0.344
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
24/69 2.35G 0.03862 0.03224 0.003158 55 640: 1
Class Images Instances P R mAP50
all 60 124 0.644 0.607 0.643 0.321
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
25/69 2.35G 0.038 0.03322 0.002688 59 640: 1
Class Images Instances P R mAP50
all 60 124 0.52 0.459 0.542 0.244
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
26/69 2.35G 0.03716 0.0322 0.002437 56 640: 1
Class Images Instances P R mAP50
all 60 124 0.666 0.611 0.682 0.33
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
27/69 2.35G 0.03762 0.03201 0.002927 57 640: 1
Class Images Instances P R mAP50
all 60 124 0.621 0.718 0.698 0.367
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
31/69 2.35G 0.03674 0.03125 0.002392 50 640: 1
Class Images Instances P R mAP50
all 60 124 0.573 0.65 0.697 0.352
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
32/69 2.35G 0.03653 0.03224 0.002655 54 640: 1
Class Images Instances P R mAP50
all 60 124 0.57 0.65 0.639 0.322
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
33/69 2.35G 0.03657 0.03263 0.002156 43 640: 1
Class Images Instances P R mAP50
all 60 124 0.625 0.655 0.669 0.36
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
34/69 2.35G 0.03644 0.0318 0.002517 79 640: 1
Class Images Instances P R mAP50
all 60 124 0.673 0.628 0.65 0.315
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
35/69 2.35G 0.03589 0.03214 0.002322 57 640: 1
Class Images Instances P R mAP50
all 60 124 0.697 0.634 0.678 0.368
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
36/69 2.35G 0.03553 0.03124 0.002237 52 640: 1
Class Images Instances P R mAP50
all 60 124 0.702 0.66 0.701 0.369
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
37/69 2.35G 0.03639 0.03221 0.001992 64 640: 1
Class Images Instances P R mAP50
all 60 124 0.643 0.697 0.672 0.356
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
38/69 2.35G 0.03528 0.03118 0.002051 53 640: 1
Class Images Instances P R mAP50
all 60 124 0.658 0.631 0.67 0.352
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
39/69 2.35G 0.03554 0.03098 0.001782 42 640: 1
Class Images Instances P R mAP50
all 60 124 0.641 0.659 0.703 0.337
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
40/69 2.35G 0.03527 0.03145 0.001548 49 640: 1
Class Images Instances P R mAP50
all 60 124 0.672 0.679 0.721 0.374
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
41/69 2.35G 0.03571 0.03147 0.001659 58 640: 1
Class Images Instances P R mAP50
all 60 124 0.728 0.617 0.702 0.377
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
42/69 2.35G 0.03504 0.03086 0.001852 48 640: 1
Class Images Instances P R mAP50
all 60 124 0.669 0.626 0.68 0.369
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
43/69 2.35G 0.03468 0.03048 0.001757 52 640: 1
Class Images Instances P R mAP50
all 60 124 0.66 0.609 0.654 0.328
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
44/69 2.35G 0.0349 0.03125 0.001606 55 640: 1
Class Images Instances P R mAP50
all 60 124 0.672 0.646 0.699 0.346
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
48/69 2.35G 0.03405 0.03076 0.001546 56 640: 1
Class Images Instances P R mAP50
all 60 124 0.707 0.639 0.707 0.37
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
49/69 2.35G 0.0346 0.03047 0.001458 58 640: 1
Class Images Instances P R mAP50
all 60 124 0.734 0.639 0.711 0.369
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
50/69 2.35G 0.03389 0.03134 0.001409 66 640: 1
Class Images Instances P R mAP50
all 60 124 0.627 0.704 0.716 0.397
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
51/69 2.35G 0.03325 0.03028 0.001466 56 640: 1
Class Images Instances P R mAP50
all 60 124 0.687 0.628 0.703 0.372
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
52/69 2.35G 0.03395 0.03087 0.001405 55 640: 1
Class Images Instances P R mAP50
all 60 124 0.643 0.713 0.738 0.405
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
53/69 2.35G 0.03332 0.03026 0.001586 76 640: 1
Class Images Instances P R mAP50
all 60 124 0.721 0.634 0.713 0.385
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
54/69 2.35G 0.03341 0.03028 0.00154 50 640: 1
Class Images Instances P R mAP50
all 60 124 0.631 0.66 0.695 0.354
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
55/69 2.35G 0.03331 0.0293 0.00161 52 640: 1
Class Images Instances P R mAP50
all 60 124 0.702 0.669 0.728 0.392
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
56/69 2.35G 0.03322 0.03058 0.001471 61 640: 1
Class Images Instances P R mAP50
all 60 124 0.633 0.748 0.729 0.41
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
57/69 2.35G 0.03292 0.03025 0.001636 63 640: 1
Class Images Instances P R mAP50
all 60 124 0.739 0.675 0.737 0.4
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
58/69 2.35G 0.03289 0.03107 0.001286 53 640: 1
Class Images Instances P R mAP50
all 60 124 0.606 0.689 0.699 0.383
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
59/69 2.35G 0.03278 0.03055 0.001203 58 640: 1
Class Images Instances P R mAP50
all 60 124 0.62 0.68 0.703 0.378
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
64/69 2.35G 0.03166 0.02994 0.001321 67 640: 1
Class Images Instances P R mAP50
all 60 124 0.68 0.707 0.727 0.398
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
65/69 2.35G 0.03225 0.03032 0.0009906 56 640: 1
Class Images Instances P R mAP50
all 60 124 0.732 0.706 0.732 0.403
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
66/69 2.35G 0.03212 0.03041 0.00102 71 640: 1
Class Images Instances P R mAP50
all 60 124 0.728 0.719 0.746 0.415
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
67/69 2.35G 0.03151 0.02948 0.001617 36 640: 1
Class Images Instances P R mAP50
all 60 124 0.67 0.684 0.719 0.399
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
68/69 2.35G 0.03154 0.02955 0.00113 57 640: 1
Class Images Instances P R mAP50
all 60 124 0.721 0.673 0.731 0.409
Epoch GPU_mem box_loss obj_loss cls_loss Instances Size
69/69 2.35G 0.03151 0.03004 0.001312 49 640: 1
Class Images Instances P R mAP50
all 60 124 0.673 0.677 0.743 0.411
70 epochs completed in 0.653 hours.
Optimizer stripped from runs/train/exp/weights/last.pt, 3.9MB
Optimizer stripped from runs/train/exp/weights/best.pt, 3.9MB
Validating runs/train/exp/weights/best.pt...
Fusing layers...
Model summary: 157 layers, 1767283 parameters, 0 gradients, 4.2 GFLOPs
Class Images Instances P R mAP50
all 60 124 0.717 0.719 0.746 0.417
crazing 60 18 0.617 0.278 0.44 0.12
inclusion 60 27 0.448 0.571 0.505 0.234
patches 60 26 0.836 0.923 0.913 0.593
pitted_surface 60 14 0.943 1 0.995 0.771
rolled-in_scale 60 19 0.751 0.842 0.838 0.412
scratches 60 20 0.707 0.7 0.785 0.372
Results saved to [1mruns/train/exp[0m
[34m[1mwandb[0m: WARNING ⚠️ wandb is deprecated and will be removed in a future release. See supported integrations at https://github.com/ultralytics/yolov5#integrations.
Exception ignored in:
Traceback (most recent call last):
File "/opt/conda/lib/python3.7/site-packages/torch/utils/data/dataloader.py", line 1358, in __del__
File "/opt/conda/lib/python3.7/site-packages/torch/utils/data/dataloader.py", line 1283, in _shutdown_workers
AttributeError: 'NoneType' object has no attribute 'python_exit_status'
Exception ignored in:
Traceback (most recent call last):
File "/opt/conda/lib/python3.7/site-packages/torch/utils/data/dataloader.py", line 1358, in __del__
File "/opt/conda/lib/python3.7/site-packages/torch/utils/data/dataloader.py", line 1283, in _shutdown_workers
AttributeError: 'NoneType' object has no attribute 'python_exit_status'
# -- img
!python train.py --img 640 --batch 16 --epochs 60 --data ./data.yaml --weights yolov5n.pt
Model summary: 157 layers, 1767283 parameters, 0 gradients, 4.2 GFLOPs
Class Images Instances P R mAP50
all 60 124 0.64 0.683 0.745 0.39
crazing 60 18 0.625 0.278 0.544 0.175
inclusion 60 27 0.444 0.563 0.553 0.255
patches 60 26 0.639 0.886 0.895 0.548
pitted_surface 60 14 0.867 0.931 0.986 0.711
rolled-in_scale 60 19 0.623 0.737 0.737 0.315
scratches 60 20 0.641 0.7 0.757 0.333
# -- img
!python train.py --img 640 --batch 16 --epochs 70 --data ./data.yaml --weights yolov5n.pt
Model summary: 157 layers, 1767283 parameters, 0 gradients, 4.2 GFLOPs
Class Images Instances P R mAP50
all 60 124 0.717 0.719 0.746 0.417
crazing 60 18 0.617 0.278 0.44 0.12
inclusion 60 27 0.448 0.571 0.505 0.234
patches 60 26 0.836 0.923 0.913 0.593
pitted_surface 60 14 0.943 1 0.995 0.771
rolled-in_scale 60 19 0.751 0.842 0.838 0.412
scratches 60 20 0.707 0.7 0.785 0.372
!ls
%cd runs
%cd train/exp
%ls
真实标签
val_batch1_labels_path = "/kaggle/working/yolov5/runs/train/exp/val_batch1_labels.jpg"
img = cv.imread(val_batch1_labels_path)
type(img)
plt.figure(figsize=(15, 15))
plt.imshow(img)
预测效果
val_batch1_pred_path = "/kaggle/working/yolov5/runs/train/exp/val_batch1_pred.jpg"
img = cv.imread(val_batch1_pred_path )
type(img)
plt.figure(figsize=(15, 15))
plt.imshow(img)
%cd /kaggle/working/yolov5
%ls
!python detect.py --source /kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid/images/crazing_1.jpg --weights /kaggle/working/yolov5/runs/train/exp/weights/best.pt
%cd /kaggle/working/yolov5/runs/detect/exp/
%ls
crazing_1_path = "/kaggle/working/yolov5/runs/detect/exp/crazing_1.jpg"
img = cv.imread(crazing_1_path)
plt.imshow(img)
竞赛需要提交 CSV 格式的文件
%cd /kaggle/working/yolov5
%ls
from utils.dataloaders import *
from utils.general import *
# datasets.py 里有 LoadImages 方法 、letterbox 方法
# general.py 里有 non_max_suppression 方法
def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None):
# Rescale coords (xyxy) from img1_shape to img0_shape
if ratio_pad is None: # calculate from img0_shape
gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1]) # gain = old / new
pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2 # wh padding
else:
gain = ratio_pad[0][0]
pad = ratio_pad[1]
coords[:, [0, 2]] -= pad[0] # x padding
coords[:, [1, 3]] -= pad[1] # y padding
coords[:, :4] /= gain
clip_coords(coords, img0_shape)
return coords
def clip_coords(boxes, img_shape):
# Clip bounding xyxy bounding boxes to image shape (height, width)
boxes[:, 0].clamp_(0, img_shape[1]) # x1
boxes[:, 1].clamp_(0, img_shape[0]) # y1
boxes[:, 2].clamp_(0, img_shape[1]) # x2
boxes[:, 3].clamp_(0, img_shape[0]) # y2
def detect1Image(im0, imgsz, model, device, conf_thres, iou_thres):
img = letterbox(im0, new_shape=imgsz)[0]
# Convert
img = img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB, to 3x416x416
img = np.ascontiguousarray(img)
img = torch.from_numpy(img).to(device)
img = img.float() # uint8 to fp16/32
img /= 255.0
if img.ndimension() == 3:
img = img.unsqueeze(0)
# Inference
pred = model(img, augment=False)[0]
# Apply NMS
pred = non_max_suppression(pred.cpu(), conf_thres, iou_thres)
boxes = []
scores = []
class_names = []
for i, det in enumerate(pred): # detections per image
# save_path = 'draw/' + image_id + '.jpg'
if det is not None and len(det):
# Rescale boxes from img_size to im0 size
det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()
# Write results
for *xyxy, conf, cls in det:
boxes.append([int(xyxy[0]), int(xyxy[1]), int(xyxy[2]), int(xyxy[3])])
scores.append(conf)
class_names.append(cls)
return np.array(boxes), np.array(scores), np.array(class_names)
def format_prediction_string(class_names, scores, boxes):
pred_strings = []
for j in zip(class_names, scores, boxes):
pred_strings.append("{0} {1:.4f} {2} {3} {4} {5}".format(j[0], j[1], j[2][0], j[2][1], j[2][2], j[2][3]))
return " ".join(pred_strings)
source = '/kaggle/input/neu-det-yolo/NEU-DET-YOLO/valid/images'
weights = '/kaggle/working/yolov5/runs/train/exp/weights/best.pt'
if not os.path.exists(weights):
print('best.pt 路径不对')
imgsz = 640
conf_thres = 0.5
iou_thres = 0.6
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
imagenames = os.listdir(source)
# 导入模型
model = torch.load(weights, map_location=device)['model'].float() # load to FP32
model.to(device).eval()
# 导入图片
dataset = LoadImages(source, img_size=imgsz)
# 记录预测结果
results = []
# 预测结果随机展示
# fig, ax = plt.subplots(5, 2, figsize=(30, 70))
# 计数,用于展示 10 张图
count = 0
for name in imagenames:
image_id = name.split('.')[0]
# 读入图片
im01 = cv2.imread('%s/%s.jpg'%(source,image_id)) # BGR
assert im01 is not None, 'Image Not Found '
im_w, im_h = im01.shape[:2]
# boxes 矩形框 xyxy,scores:[confidence, class]
boxes, scores, class_names = detect1Image(im01, imgsz, model, device, conf_thres, iou_thres)
print('图像的ID : ', image_id)
print('图像的 boxes :', boxes)
print('图像的 scores :',scores)
print('图像的 class_names :',class_names)
if boxes is not None:
# for boxe in boxes:
# boxes[:, 2] = boxes[:, 2] - boxes[:, 0]
# boxes[:, 3] = boxes[:, 3] - boxes[:, 1]
boxes = boxes[scores >= 0.05].astype(np.int32)
scores = scores[scores >=float(0.05)]
result = {
'image_id': image_id,
'PredictionString': format_prediction_string(class_names, scores, boxes)
}
results.append(result)
test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])
# test_df.to_csv('submission.csv', index=False)
test_df.head()
路径转化到 Output
%ls
test_df.to_csv('submission.csv', index=False)