【校园AI Day-AI workshop】卷积神经网络可解释缺陷检测
时间:2025-08-09
-
-
850豪华版安卓正版
- 类型:
- 大小:
- 语言:简体中文
- 评分:
- 查看详情
【校园AI Day-AI workshop】卷积神经网络可解释缺陷检测
本项目旨在解决工业工件表面缺陷检测中的主观化和低效率问题以及标签不完整的难题。首先,我们采用百度飞桨PaddleX框架构建分类网络来完成图像的分类任务。随后,通过卷积特征图生成热力图,利用阈值分割和轮廓查找技术实现对缺陷部位的精准定位。此外,提供了详细的环境配置、数据准备以及模型训练的代码实现流程,帮助相关开发者快速上手此方法。

1、项目说明
在复杂的生产过程中难以避免产出表面带有缺陷的劣质工件。工件表面存在 缺陷不仅影响其外观质量,还影响其使用寿命与稳定性,由于复杂的生产工艺以及不确定的环境因素难以避免生产出一些表面带有缺陷的劣质工件。工件表面存在缺陷直接影响工件的外观质量,工件外观质量又决定着工件的价值,且直接关系着使用过程中的安全性和稳定性。
例如:

传统的工件表面缺陷检测方式通常依赖于人工操作,这一方法存在着显著的局限性。由于技术人员的人为因素,如经验、认知偏差和主观判断能力,以及环境条件的变化(例如光照强度与温度)的影响,导致了检测结果的不一致性和标准化不足。长时间的工作可能会使员工产生精神疲惫或视觉疲劳,这不仅影响工作效率,还会降低其对细节的关注度,从而增加了漏检和误检的可能性。此外,对于微小缺陷或者颜色、纹理不明显的工件表面,人工检测同样变得困难重重。由于接触式检测方法依赖于与工件的直接接触,可能会对某些敏感部位造成二次损伤。同时,基于人手的检测方式也存在效率低下和成本高昂的问题。当需要处理大量样本时,传统的人工操作难以满足快速、高效的需求,导致工作效率低下的问题更加突出。然而,这些局限性并非是不可克服的。通过引入自动化设备和技术,如机器学习算法和深度学习模型,可以实现对工件表面缺陷的自动检测与分析。这种智能方法不仅能减少人为误差,提升检测效率,还能在一定程度上减轻员工的工作负担。另外,利用图像处理技术,可以通过颜色模式、纹理特征等特征提取来辅助人工检测或者进一步提高自动化检测的效果。这些改进措施结合了传统的人工经验和智能化的现代工具,为实际应用中解决了标签不完整、无边框标注信息等问题提供了有效的解决方案。综上所述,虽然传统的手工检测方式存在诸多局限性,但通过引入和利用现代技术手段(如人工智能、图像处理等),我们可以大大提升工件表面缺陷检测的效果,从而提高生产效率,减少人为错误,并且能够应对传统方法难以解决的复杂问题。
本项目内容为工业上工件表面缺陷分类,完成工件缺乏边框标注信息的缺陷定位。
2、项目方案
2.1 图像分类
使用百度飞浆PaddleX快速构建分类网络
PaddleX 是一款集成了飞桨智能视觉领域图像分类、目标检测、语义分割和实例分割功能的工具,实现了深度学习开发的全流程,从数据准备到模型训练与优化,再到多端部署的一站式解决方案。它提供了一个统一的任务API接口和图形化开发界面示例,使开发者只需低代码的形式即可快速完成飞桨的全过程开发。
2.2 缺陷定位
通过卷积特征图计算出热力图,并将其RGB通道分离,针对G通道设置阈值分割以识别缺陷区域。当像素点的灰度值超过设定的阈值时,输出为反之则输出为接着利用二值图像进行轮廓查找,提取外侧轮廓并求得其外接矩形,完成对缺陷部位的定位分析。
Sij={255,heatmapij>th0,otherwiseSij={255,heatmapij>th0,otherwise
3、代码实现
3.0 环境配置
In []
#安装paddlex!pip install paddlex==2.1.0登录后复制
3.1 数据集准备
在这个项目中,我们利用了著名的mvtec_ad数据集来处理工业质量检查任务。该数据集包含别的汽车地毯样本,并分为训练集、验证集和测试集,已保存至mydata和grid文件夹内。
#解压数据集!unzip -o -q -d /home/aistudio/work /home/aistudio/data/data116256/mvtec_anomaly_detection.zip登录后复制 In [9]
批量修改文件名import os#设定文件路径path='work/grid/test/broken'i=对目录下的文件进行遍历for file in os.listdir(path): if os.path.isfile(os.path.join(path,file))==True:#设置新文件名new_name=file.replace(file,"broken_%d.png"%i)#重命名os.rename(os.path.join(path,file),os.path.join(path,new_name)) i+=结束print("End")
End登录后复制 In []
#移动图片到mydata目录import shutil#这个库复制文件比较省事import osfrom PIL import Image dirname_read="work/grid/test/thread/" # 注意后面的斜杠dirname_write="grid/notgood/"names_all=os.listdir(dirname_read)def file_filter(f): if f[-4:] in ['.jpg', '.png', '.bmp']: return True else: return Falsepicture_nmmes = list(filter(file_filter, names_all))print(picture_nmmes)print(len(picture_nmmes))print(dirname_read)for i in picture_nmmes: new_obj_name = i print(new_obj_name) shutil.copy(dirname_read + '/' + new_obj_name, dirname_write + '/' + new_obj_name)登录后复制 In []
#划分carpet数据集!paddlex --split_dataset --format ImageNet --dataset_dir mydata --val_value 0.2 --test_value 0.1登录后复制 In []
#划分grid数据集!paddlex --split_dataset --format ImageNet --dataset_dir grid --val_value 0.2 --test_value 0.1登录后复制
3.2 训练分类模型
训练模型
train训练参数
改进后的在深度学习项目中,我们经常需要通过调整超参数来优化模型的性能和准确性。为了方便研究、比较不同的算法或评估实验结果,我们可以使用预训练权重或者自定义训练数据集来进行迁移学习。以下是根据您提供的信息设计的一个新的假设--- 模型训练与评估在深度学习项目中,我们常常需要调整超参数来优化模型的性能和准确性。为了方便研究、比较不同的算法或评估实验结果,我们可以使用预训练权重或者自定义训练数据集来进行迁移学习。以下是根据您的提供的信息设计的一个新的假设# 参数说明 迭代轮数 (`num_epochs`): 训练过程中的总迭代次数。 训练数据读取器 (`train_dataset`): 提供用于训练模型的数据源。 batch大小 (train_batch_size): 每个训练批次包含的样本数量,同时它也是验证批次的数量。默认值为 验证数据读取器 (`eval_dataset`): 用于评估模型性能的数据集。 模型保存间隔 (save_interval_epochs): 模型在多长时间内进行一次保存。默认值为 日志输出间隔 (log_interval_steps): 日志信息每隔多少步进行记录。默认值为 模型保存路径 (`save_dir`): 存储训练结果的目录,例如:`./saved-models/weights-epoch-loss-. 预训练模型选择 (`pretrain_weights`): - `None`: 不使用任何预训练权重。 - `'IMAGENET'`: 自动从ImageNet上下载预训练权重。 - `'BAIDU'`: 自动下载百度自研的类预训练模型。 优化器 (`optimizer`): 默认情况下,使用PaddlePaddle中的优化策略和Momentum算法。若参数为None,则不使用任何优化器。 初始学习率 (`learning_rate`): 默认值为 warmup阶段 (warmup_steps): 训练过程中从warmup_start_lr到learning_rate所需步数,默认为 学习率衰减轮数 (`lr_decay_epochs`): 衰减的学习率周期,如[ 。 学习率衰减比率 (`lr_decay_gamma`): 前向传播中权重的衰减因子,默认为 视觉化工具 (`use_vdl`): 是否使用VisualDL进行训练过程可视化。默认设置为False。 敏感度信息裁剪 (`sensitivities_file`): 在进行模型裁剪时,提供用于调整网络参数的敏感度信息。默认值为None。# 超参数示例```python num_epochs = train_dataset = paddlex.datasets.ImageDataset(root_dir='./data/train') eval_dataset = paddlex.datasets.ImageDataset(root_dir='./data/val')save_interval_epochs = 5 log_interval_steps = pretrain_weights = 'BAIDU' optimizer = None learning_rate = armup_steps = lr_decay_epochs = [ lr_decay_gamma = se_vdl = False sensitivities_file = 'path/to/sensitivity/info'early_stop = True early_stop_patience = esume_checkpoint = './saved-models/weights-epoch-loss- ```# 复杂性与挑战模型训练和评估是一个复杂的过程,涉及到多个参数的调整和验证。例如,学习率的选择和衰减策略需要平衡过拟合和欠拟合之间的矛盾;batch大小的选择对训练速度有直接影响但同时也影响了模型在测试集上的表现。使用预训练权重或自定义数据集可以帮助我们更快地优化算法,并且通过这些参数的调整我们可以找到最适合当前任务的最佳设置。然而,这也会涉及到大量的实验时间和资源投入,因此在开始时需要谨慎规划和执行。
# 设置使用0号GPU卡(如无GPU,执行此代码后仍然会使用CPU训练模型)import matplotlib matplotlib.use('Agg') import os os.environ['CUDA_VISIBLE_DEVICES'] = '0'import paddlex as pdximport paddlex as pdxfrom paddlex import transforms as T train_transforms = T.Compose( [T.RandomCrop(crop_size=224), T.RandomHorizontalFlip(), T.Normalize()]) eval_transforms = T.Compose([ T.ResizeByShort(short_size=256), T.CenterCrop(crop_size=224), T.Normalize() ])# 定义训练和验证所用的数据集# API说明:https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/apis/datasets.mdtrain_dataset = pdx.datasets.ImageNet( data_dir='grid', file_list='grid/train_list.txt', label_list='grid/labels.txt', transforms=train_transforms, shuffle=True) eval_dataset = pdx.datasets.ImageNet( data_dir='grid', file_list='grid/val_list.txt', label_list='grid/labels.txt', transforms=eval_transforms)# 初始化模型,并进行训练# 可使用VisualDL查看训练指标,参考https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/visualdl.mdnum_classes = len(train_dataset.labels) model = pdx.cls.ResNet50_vd(num_classes=num_classes) model.train( num_epochs=80, train_dataset=train_dataset, train_batch_size=8, eval_dataset=eval_dataset, lr_decay_epochs=[4, 6, 8], learning_rate=0.01, save_dir='output/grid', use_vdl=True)登录后复制
3.3 模型预测
In [30]
import paddlex as pdx model = pdx.load_model('output/ResNet50_vd/best_model') image_name = 'mydata/notgood/000.png'result = model.predict(image_name)str=result[0]print("Predict Result:", result)if str['category_id'] : print("有缺陷")else: print("无缺陷")登录后复制
- 05-27 16:56:52 [INFO] Model[ResNet50_vd] loaded. Predict Result: [{'category_id': 1, 'category': 'notgood', 'score': 0.737099}] 有缺陷登录后复制
3.4 输出结果
进行模型预测,并输出神经网络热力图,完成缺陷定位。
输出结果保存在Heatmap/result.png In [1]
%matplotlib inlineimport osfrom PIL import Imageimport paddleimport numpy as npimport cv2import matplotlib.pyplot as pltfrom draw_features import Res2Net_vdimport draw_featuresimport paddle.nn.functional as Fimport paddleimport warnings warnings.filterwarnings('ignore')def draw_CAM(model, img_path, save_path, transform=None, visual_heatmap=False): ''' 绘制 Class Activation Map :param model: 加载好权重的Pytorch model :param img_path: 测试图片路径 :param save_path: CAM结果保存路径 :param transform: 输入图像预处理方法 :param visual_heatmap: 是否可视化原始heatmap(调用matplotlib) :return: ''' # 图像加载&预处理 img = Image.open(img_path).convert('RGB') img = img.resize((224, 224), Image.BILINEAR) #Image.BILINEAR双线性插值 if transform: img = transform(img) # img = img.unsqueeze(0) img = np.array(img).astype('float32') img = img.transpose((2, 0, 1)) img = paddle.to_tensor(img) img = paddle.unsqueeze(img, axis=0) # print(img.shape) # 获取模型输出的feature/score output,features = model(img) print('outputshape:',output.shape) print('featureshape:',features.shape) # lab = np.argmax(out.numpy()) # 为了能读取到中间梯度定义的辅助函数 def extract(g): global features_grad features_grad = g # 预测得分最高的那一类对应的输出score pred = np.argmax(output.numpy()) # print('***********pred:',pred) pred_class = output[:, pred] # print(pred_class) features.register_hook(extract) pred_class.backward() # 计算梯度 grads = features_grad # 获取梯度 # print(grads.shape) # pooled_grads = paddle.nn.functional.adaptive_avg_pool2d( x = grads, output_size=[1, 1]) pooled_grads = grads # 此处batch size默认为1,所以去掉了第0维(batch size维) pooled_grads = pooled_grads[0] # print('pooled_grads:', pooled_grads.shape) # print(pooled_grads.shape) features = features[0] # print(features.shape) # 最后一层feature的通道数 for i in range(2048): features[i, ...] *= pooled_grads[i, ...] heatmap = features.detach().numpy() heatmap = np.mean(heatmap, axis=0) # print(heatmap) heatmap = np.maximum(heatmap, 0) # print('+++++++++',heatmap) heatmap /= np.max(heatmap) # print('+++++++++',heatmap) # 可视化原始热力图 if visual_heatmap: plt.matshow(heatmap) plt.show() img = cv2.imread(img_path) # 用cv2加载原始图像 heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0])) # 将热力图的大小调整为与原始图像相同 heatmap = np.uint8(255 * heatmap) # 将热力图转换为RGB格式 cv2.imwrite('Heatmap/heatmap.png',heatmap);#将热力图保存到硬盘 heatmap1 =heatmap # print(heatmap.shape) heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET) # 将热力图应用于原始图像 superimposed_img = heatmap * 0.4 + img # 这里的0.4是热力图强度因子 cv2.imwrite(save_path, superimposed_img) # 将图像保存到硬盘 the =220 # 设置阈值 maxval = 255 dst, heatmap1 = cv2.threshold(heatmap1, the, maxval, cv2.THRESH_BINARY) cnts = cv2.findContours(heatmap1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] #画出轮廓 for c in cnts: x,y,w,h = cv2.boundingRect(c) cv2.rectangle(img, (x, y), (x + w, y + h), (36,255,12), 2) cv2.imwrite('Heatmap/result.png',img);# 将图像保存到硬盘model_re2 = Res2Net_vd(layers=50, scales=4, width=26, class_dim=4)# model_re2 = Res2Net50_vd_26w_4s(class_dim=4)modelre2_state_dict = paddle.load("output/ResNet50_vd/best_model/model.pdparams") model_re2.set_state_dict(modelre2_state_dict, use_structured_name=True) use_gpu = Truepaddle.set_device('gpu:0') if use_gpu else paddle.set_device('cpu') model_re2.eval()import paddlex as pdx model = pdx.load_model('output/ResNet50_vd/best_model')#模型路径image_name = 'mydata/notgood/000.png'#输入图片路径result = model.predict(image_name)print("Predict Result:", result)str=result[0]if str['category_id'] : print("有缺陷") draw_CAM(model_re2, image_name, 'Heatmap/Heatmap.png', transform=None, visual_heatmap=True)else: print("无缺陷")登录后复制
W0602 00:36:36.333329 20180 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.2, Runtime API Version: 10.1 W0602 00:36:36.338220 20180 device_context.cc:465] device: 0, cuDNN Version: 7.6.登录后复制
[06-02 00:36:39 MainThread @utils.py:79] WRN paddlepaddle version: 2.2.2. The dynamic graph version of PARL is under development, not fully tested and supported 2022-06-02 00:36:40 [INFO] Model[ResNet50_vd] loaded. Predict Result: [{'category_id': 1, 'category': 'notgood', 'score': 0.737099}] 有缺陷 outputshape: [1, 4] featureshape: [1, 2048, 7, 7]登录后复制
<Figure size 288x288 with 1 Axes>登录后复制
3.5 效果展示

grid效果!

以上就是【校园AI Day-AI workshop】卷积神经网络可解释缺陷检测的详细内容,更多请关注其它相关文章!