A095-segformer模型实现pcb缺陷检测

A095-segformer模型实现pcb缺陷检测

导出时间:2026/1/14 20:41:46

1. 项目简介

本项目旨在开发一个基于深度学习的自动化缺陷分割系统,用于工业制造领域的质量控制与检测。近年来,随着工业4.0的推进,生产过程中对质量检测的自动化和精准性要求愈发严格,传统检测方法往往难以满足复杂场景的需求,尤其是微小缺陷和异形物体表面缺陷的精准识别与分割。因此,利用深度学习模型在计算机视觉领域的显著性能提升,能够有效解决这些难点。本项目采用卷积神经网络(Convolutional Neural Networks, CNNs)及其变体模型(如U-Net、Mask R-CNN等)实现高效缺陷检测和分割。U-Net网络因其独特的编码-解码结构和跳跃连接,能在分割任务中提供高分辨率的预测,适用于目标边界复杂的工业场景,而其他模型如ResNet或DenseNet等则可增强特征提取能力。此外,项目结合数据增强和迁移学习等技术,提升模型在不同材质、纹理以及光照条件下的泛化能力,从而确保实际生产中的鲁棒性和可靠性。本项目的目标是通过构建并优化深度学习模型,以满足实时性和高精度检测的需求,为工业制造流程提供智能化质量监控解决方案,减少人工成本并提高生产效率。

3. 数据集与预处理

image.png

image.png

image.png
本项目的数据集来源于工业制造领域的实际生产环境,主要包括印刷电路板(PCB)上的缺陷图像及其对应的标注文件。这些图像涵盖了各种常见缺陷类型,如短路、虚焊和安装错误等,具有高度的多样性和复杂性,包括不同的纹理、光照条件以及缺陷形态。标注文件采用XML格式,包含详细的多边形坐标,用于精确描绘每个缺陷的边界。这种多边形标注方式相较于传统的矩形边界框能够提供更高的标注精度,尤其在处理不规则形状的缺陷时表现出显著优势。
在数据预处理方面,项目首先对原始图像进行了归一化处理,将像素值缩放到[0, 1]区间,以加快模型的收敛速度并提高训练的稳定性。随后,为了增强数据的多样性并防止模型过拟合,采用了多种数据增强技术。这包括水平翻转、颜色抖动和随机旋转等,通过Albumentations库实现。这些增强操作模拟了实际环境中的各种变动,帮助模型更好地应对复杂和多变的生产条件。此外,针对不同缺陷的分布特点,进行了定制化的数据平衡措施,确保训练集中各类缺陷样本的均衡分布。
在特征工程方面,本项目重点进行了缺陷mask的生成与优化处理。具体来说,通过解析XML标注文件中的多边形坐标,使用OpenCV生成像素级别的分割掩码,确保与原图像完美对齐。这一过程不仅提升了数据的标注质量,还为模型提供了准确的分割目标。此外,为了提升特征表达能力,项目采用了Segformer预处理器,将图像和mask转换为模型可接受的张量格式,同时进行尺寸调整和归一化处理,以适应深度学习模型的输入要求。通过这些全面的预处理步骤,本项目确保了数据的高质量输入,为深度学习模型的高效训练奠定了坚实基础。

4. 模型架构

  1. 模型结构的逻辑 本项目采用了Segformer架构,这是一种基于Transformer的语义分割模型,结合了轻量化和高效性的设计。Segformer模型通过高效的混合Transformer编码器和解码器实现像素级语义分割。编码器利用Transformer模块捕获全局上下文信息,同时保留图像的细节特征,并通过多尺度特征聚合提高分割精度。具体来说,本项目加载了NVIDIA发布的“mit-b0”预训练模型,以充分利用大规模预训练权重的优势,并进行了模型微调以适应工业缺陷分割任务。模型在输出层映射到多类标签,用于预测不同的缺陷类别(如短路、虚焊和错误安装等)。
  2. 模型的整体训练流程 模型训练分为数据加载、模型构建与配置、训练与评估几个主要步骤。首先,创建自定义的数据集类DefectSegmentationDataset,从图像路径和XML标注文件中加载图像和对应的缺陷mask,并通过SegformerImageProcessor进行预处理。然后,加载预训练的Segformer模型并设置训练参数,如学习率(0.00001)、训练周期(50轮)、批量大小(1)等。通过Hugging Face的TrainingArguments进行训练配置,使用步骤(steps)作为评估和保存策略,以在每隔指定的步数后评估模型性能和保存检查点。
模型训练使用Trainer类进行封装,训练过程中每个评估周期都计算评估指标。评估指标采用平均交并比(Mean Intersection over Union, mIoU),这是语义分割任务中常用的标准,计算预测掩码与真实掩码的重合度。此外,mIoU结果会分解为每个类别的精度(accuracy)和交并比(IoU),从而详细评估模型在不同缺陷类型上的表现。
在训练结束后,保存最佳模型权重,并使用推理流程进行模型测试。测试图像通过预处理器标准化输入模型,输出掩码通过双线性插值调整到原图像尺寸,并使用类别映射将预测的类别索引转换为实际颜色值进行可视化,最终生成缺陷分割图。

5. 核心代码详细讲解

1. 数据预处理与特征工程

image.png

def process_mask(img_path, xml_path, visualize=False):# 读取图像,并初始化一个空的掩码(mask),大小与图像一致
    img = cv2.imread(img_path)
    # 如果visualize=True,则创建一个3通道的RGB掩码,否则创建单通道掩码
    num_dim = 3 if visualize else 1
    mask = np.zeros((img.shape[0], img.shape[1], num_dim))
    # 读取XML文件内容并解析为字典格式with open(xml_path, "r") as file:
        xml_content = file.read()
    data = xmltodict.parse(xml_content)
# 检查XML标注中是否包含缺陷信息if "object" in data["annotation"]:
        objects = data["annotation"]["object"]
# 如果只有一个缺陷对象,则将其转换为列表格式,以便统一处理if not isinstance(objects, List):
            objects = [objects]
# 遍历每个缺陷对象,获取缺陷类型和多边形坐标for obj in objects:
            defect_type = obj["name"]
            polygon = obj["polygon"]
            poly_keys = list(polygon.keys())
# 解析多边形坐标点的数量
            poly_keys = [int(k[1:]) for k in poly_keys]
            num_poly_points = max(poly_keys)
# 将多边形的坐标点依次提取并存入数组
            poly_coords = []for i in range(1, num_poly_points + 1):
                poly_coords.append([int(float(polygon[f"x{i}"])),int(float(polygon[f"y{i}"]))
                ])
            poly_coords = np.array(poly_coords)
# 使用OpenCV在掩码中填充多边形区域
            fill_color = color_map[defect_type] if visualize else id_cat_map[defect_type]
            mask = cv2.fillPoly(mask, pts=[poly_coords], color=fill_color)
    # 如果是可视化模式,保存掩码图像if visualize:
        cv2.imwrite("output.jpg", mask)
        mask = Image.open("output.jpg")
    return mask
代码详解:
  • img = cv2.imread(img_path): 使用OpenCV读取图像文件,并存入img变量中。
  • mask = np.zeros((img.shape[0], img.shape[1], num_dim)): 初始化一个空的掩码数组,与图像的大小相同。num_dim为3时创建RGB掩码,为1时创建单通道掩码。
  • xmltodict.parse(xml_content): 解析XML格式的标注文件,将其转换为字典格式,方便后续的数据提取。
  • if "object" in data["annotation"]: 检查标注文件中是否存在缺陷对象。
  • if not isinstance(objects, List): 处理单个缺陷对象,将其包装为列表,便于统一遍历处理。
  • for obj in objects: 遍历所有缺陷对象,提取缺陷类型和多边形坐标。
  • poly_coords.append([...]): 将多边形的每个坐标点提取并存入poly_coords数组。
  • mask = cv2.fillPoly(...): 使用OpenCV的fillPoly函数,在掩码上绘制缺陷多边形区域。
  • cv2.imwrite("output.jpg", mask): 如果启用了可视化模式,将掩码图像保存并加载为PIL图像进行展示。

2. 模型架构构建

image.png

id2label = {0: "background", 1: "Short_circuit", 2: "Dry_joint", 3: "Incorrect_installation"}
label2id = {label: id for id, label in id2label.items()}
num_labels = len(id2label)

# 加载预训练的Segformer模型
pretrained_model_name = "nvidia/mit-b0"
model = SegformerForSemanticSegmentation.from_pretrained(
    pretrained_model_name,
    id2label=id2label,
    label2id=label2id
)
代码详解:
  • id2labellabel2id: 建立类别标签和类别ID之间的映射,确保模型可以正确地将预测输出转换为实际类别标签。
  • num_labels = len(id2label): 计算总的类别数,用于定义模型的输出维度。
  • pretrained_model_name = "nvidia/mit-b0": 指定使用的预训练模型名称,这里选择了Segformer的MIT-B0版本,轻量且高效。
  • SegformerForSemanticSegmentation.from_pretrained(...): 从Hugging Face Transformers库中加载预训练的Segformer模型,并配置类别标签映射,以适应语义分割任务。

3. 模型训练与评估

image.png

# 设置训练参数
epochs = 50
lr = 0.00001
batch_size = 1# 创建训练参数对象
training_args = TrainingArguments("segformer-b0-finetuned-pcb-outputs",
    learning_rate=lr,
    num_train_epochs=epochs,
    per_device_train_batch_size=batch_size,
    per_device_eval_batch_size=batch_size,
    save_total_limit=3,
    evaluation_strategy="steps",
    save_strategy="steps",
    save_steps=500,
    eval_steps=250,
    logging_steps=1,
    eval_accumulation_steps=5,
    load_best_model_at_end=True,
)
代码详解:
  • epochs = 50: 设置训练轮数为50次,以确保模型有足够的时间进行优化。
  • lr = 0.00001: 设置学习率为0.00001,控制模型的参数更新步伐,防止训练过程中出现梯度爆炸或梯度消失。
  • batch_size = 1: 设置每个设备上的批量大小为1,适应高分辨率图像分割任务的内存需求。
  • TrainingArguments(...): 定义训练过程的参数,包括学习率、训练轮数、保存策略、评估策略、日志记录频率等。
  • save_total_limit=3: 限制保存的模型检查点数量,以节省存储空间。

metric = evaluate.load("mean_iou")

def compute_metrics(eval_pred):with torch.no_grad():
        logits, labels = eval_pred
        logits_tensor = torch.from_numpy(logits)
# 调整预测输出的大小与标签尺寸一致
        logits_tensor = nn.functional.interpolate(
            logits_tensor,
            size=labels.shape[-2:],
            mode="bilinear",
            align_corners=False,
        ).argmax(dim=1)
        pred_labels = logits_tensor.detach().cpu().numpy()
# 使用Mean IoU作为评估指标
        metrics = metric._compute(
            predictions=pred_labels,
            references=labels,
            num_labels=len(id2label),
            ignore_index=None,
            reduce_labels=preprocessor.do_reduce_labels,
        )
# 提取每个类别的精度和IoU,并更新到metrics字典中
        per_category_accuracy = metrics.pop("per_category_accuracy").tolist()
        per_category_iou = metrics.pop("per_category_iou").tolist()
        metrics.update({f"accuracy_{id2label[i]}": v for i, v in enumerate(per_category_accuracy)})
        metrics.update({f"iou_{id2label[i]}": v for i, v in enumerate(per_category_iou)})
return metrics
代码详解:
  • metric = evaluate.load("mean_iou"): 加载Mean IoU评估指标,用于语义分割任务。
  • compute_metrics(eval_pred): 定义一个函数来计算评估指标,接收模型的预测结果和标签作为输入。
  • logits_tensor = nn.functional.interpolate(...): 使用双线性插值调整预测输出的大小,使其与真实标签的尺寸一致。
  • logits_tensor.argmax(dim=1): 获取每个像素的类别预测索引。
  • metrics = metric._compute(...): 计算Mean IoU及每个类别的精度和IoU,并返回结果。

6. 模型优缺点评价

模型优点 Segformer模型结合了Transformer和CNN的优势,具备卓越的上下文特征捕获能力和精细的分割性能。其轻量化设计使得推理速度快,适合实时工业应用。通过加载预训练模型,充分利用了大规模数据集上的学习特征,加速了模型的收敛。项目使用的数据增强策略(如水平翻转、颜色抖动和随机旋转)提高了模型的泛化能力,能在不同缺陷类型和复杂背景下实现稳定分割。此外,定制的mask生成流程基于XML标注的多边形坐标,确保了精确的缺陷区域分割,并结合热图分析提供了有价值的缺陷位置分布信息。
模型缺点 尽管Segformer模型性能优越,但其依赖高分辨率图像和多尺度特征聚合,可能导致较大的内存需求和计算资源消耗,尤其在处理大规模工业数据集时。使用简单的超参数配置(如固定的学习率和批量大小)限制了模型的灵活性,未能充分探索最佳训练参数。此外,模型的数据增强方法相对基础,未能充分考虑工业场景中可能出现的更复杂的环境变化,如光照强度波动或视角变化。由于训练和评估数据集有限,模型在未见过的缺陷类型或极端场景下的泛化能力可能存在不足。
改进方向 为提升模型性能,可以优化模型结构,如引入更深层次的特征提取模块,或采用混合卷积与Transformer的创新架构。进一步调整超参数(如动态学习率、较大的批量大小等),结合自动化超参数调优工具进行优化。扩展数据增强方法,例如引入仿射变换、噪声干扰、局部遮挡等,以模拟更丰富的工业场景。此外,考虑使用知识蒸馏或多任务学习,提升模型的泛化能力和训练效率。最后,增加更大规模和多样化的数据集,进一步提高模型在实际应用中的鲁棒性。
4o