简介:这是一套面向深度学习开发者与半导体质量检测工程师的完整项目资源,将mmdetection框架下的Faster-RCNN目标检测模型与DataAugmentation-ForObjectDetect数据增强技术相结合,用于半导体晶圆表面缺陷的自动识别与定位。方案从数据预处理、在线增强到模型训练与验证均提供了可运行脚本与配套说明,能够有效缓解真实场景中缺陷样本稀缺带来的过拟合问题。包内共1161个文件、约28.4MB,以Python脚本(802个)为核心,涵盖数据增强、模型训练、推理与评估全流程;另有JPG图像样本(229个)用于演示与测试,Markdown文档(91个)和Jupyter教程(2个)辅助说明思路,并附带容器化部署配置、模型配置文件与运行脚本,便于快速复现环境。目前已有368人学习下载。资源包含可运行的训练推理代码、增强策略配置、晶圆图像示例、MMDet教程笔记及演示视频,既可入门Faster-RCNN在工业质检中的实践,也可作为半导体缺陷检测项目改造的参考基线。
1. 项目概述与整体思路拆解
1.1 从标题里读出什么
先把这个项目拆开看:mmdetection框架+Faster-RCNN模型+DataAugmentation-ForObjectDetect数据增强+半导体晶圆表面缺陷识别。这条链路其实是一套完整的工业视觉质检方案,从数据处理、模型训练到缺陷分类定位全走了一遍。
半导体晶圆缺陷检测一直是制造业的刚需场景。晶圆表面的划痕、颗粒污染、图案缺失等缺陷会直接影响芯片良率,人工目检效率低不说,漏检率还高。传统机器视觉靠特征工程做模板匹配,换个光照条件就得重新调参,鲁棒性有限。深度学习目标检测进来之后,把问题转化为"在图像中找到缺陷的位置并给出类别",事情就顺多了。
这个项目选型上有一个值得琢磨的点:为什么用Faster-RCNN而不是YOLO系列?我的理解是,晶圆缺陷数据集通常规模不大,不可能像COCO那样动辄几十万张图。Faster-RCNN作为两阶段检测器,第二阶段的ROI Head可以从每个候选区域中重新提取特征做精细分类,在小数据集上往往比单阶段模型更容易收敛、误检更少。而mmdetection这个工具箱把Faster-RCNN的实现封装得很完善,数据加载、评估指标、训练调度都开箱即用,不需要自己去复现RPN(Region Proposal Network)、RoIAlign这些底层模块。
再说DataAugmentation-ForObjectDetect这个库。它和普通的数据增强库不同,专门为检测任务设计,对图像做翻转、缩放、裁剪、色彩变换时,会同步更新边界框坐标。这一点在做检测增强时极其关键,接下来会详细展开。
1.2 整体技术链路
整个项目的技术链路可以分成四段:数据准备 → 增强策略设计 → 模型训练与调优 → 模型评估与导出。每一步都有比较多的坑,下面一个个说。
数据准备阶段要把晶圆缺陷图像整理成COCO或VOC格式,同时做label检查——工业缺陷数据里经常出现标框过小、类别不均衡、标签漏标的问题,这些都会直接影响模型效果。
增强策略阶段引入DataAugmentation-ForObjectDetect,通过随机组合多种变换扩充样本空间,重点解决缺陷样本量少、缺陷形态单一的问题。
模型训练阶段在mmdetection里配置Faster-RCNN,核心是调整anchor尺寸以适配晶圆缺陷的尺度分布,以及选择合适的学习率策略防止在小数据集上过拟合。
评估导出阶段用mAP等指标评估,并考虑导出为ONNX以支持C++推理部署,实现产线实时检测。
2. 数据准备与增强方案设计
2.1 晶圆缺陷数据集的整理规范
不管用哪个检测框架,数据质量永远排在模型结构前面。晶圆缺陷数据集常见的问题是正负样本不均衡、缺陷区域占比太小、标注框不精确。如果原始数据是CSV或XML标注,第一步是统一转成COCO格式的JSON。
使用标注工具时有一点要特别留意:半导体图像通常是灰度图且背景纹理相近,标注时要放大到像素级去框,稍不留神就会把框画偏几个像素。不要觉得差几个像素无所谓,对缺陷这种小目标来说,几个像素的偏差会让IoU下降不少,最终影响AP值。我实际训练中发现,框偏移超过5个像素,小缺陷类别的AP会掉3到5个点,这个损失在后面很难补回来。
标签检查这一步可以借助一些脚本辅助。例如画出所有标注框在原图上的位置,人工快速浏览一遍,能发现不少边界框超出图像范围、类别标错的问题。这个步骤虽然土,但对后面训练省心很多。
2.2 DataAugmentation-ForObjectDetect增强策略
训练数据增强是整个项目里性价比最高的模块。晶圆缺陷样本可能只有几百张甚至几十张,靠模型硬扛很难达到产线要求,增强是绕不开的。
DataAugmentation-ForObjectDetect提供旋转、平移、缩放、翻转、随机裁剪、色彩抖动、模糊、噪声注入等操作。最核心的价值在于,它能在变换图像的同时把标注框坐标同步变换,这样增强后的数据才能用于检测任务。对比一下通用增强库(比如imgaug),这个库的接口更简单,针对检测任务做了专门的坐标处理,不用自己写映射函数。
实际使用时,关键不是用多花哨的增强,而是要"对症下药"。晶圆缺陷图像的背景相对固定,不像自然场景那样复杂多变,所以增强策略应该以几何变换为主、色彩扰动为辅:
- 水平翻转和垂直翻转:缺陷在晶圆上的分布没有方向性,翻转不改变语义,可以放心加。
- 随机旋转(90度、180度、270度):晶圆图案存在同心圆结构,旋转90度不会破坏语义。
- 随机亮度对比度调整:模拟不同光照下晶圆图像的明暗变化,提升模型对光照的鲁棒性。
- 随机裁剪(裁剪后resize回原尺寸):让模型看到缺陷的局部细节,增强对部分遮挡的容忍度。
- 马赛克增强(Mosaic):把多张图拼接成一张,增加单张图的缺陷数量。但要注意,晶圆缺陷密集区域经过拼接后可能出现语义割裂,需要针对类别特性决定是否启用。
有一种增强要小心:随机Erasing或Cutout。这类方法会把图像中随机区域置为灰色或黑色,对晶圆这种纹理周期性强的图像来说,可能会破坏背景结构,反而让模型学到错误的特征。如果缺陷区域和背景纹理很相似,加了Cutout容易误删掉真正的缺陷。
2.3 类别不均衡的处理技巧
晶圆缺陷常见类别包括划痕(Scratch)、颗粒污染(Particle)、面积缺陷(Area Defect)、边缘缺陷(Edge Defect)等。这几类的出现频率往往差异很大,划痕最多,边缘缺陷可能只有几张图。
数据增强只能缓解数量差距,没法根治。更有效的手段是类别重加权损失,在mmdetection里可以给每个类别设置不同的loss weight,让模型更加关注样本少的类别。另外还有一个思路:对数量极少的类别做过采样,把它在每轮epoch中的出现次数人为提高,配合增强生成多样化的样本。
从我实际踩坑的经验看,类别不均衡在缺陷检测中的表现不是"少样本类别完全检不出",而是"少样本类别的AP特别不稳定",这轮训完是0.4,下轮就变成0.1,让人非常抓狂。解决方向是调低模型的学习率,让训练过程更平稳,同时把多尺度训练打开,模型对不同尺寸缺陷的特征表达能力会更强。
3. mmdetection环境搭建与Faster-RCNN模型配置
3.1 mmdetection安装的版本匹配
mmdetection的安装不算难,但版本匹配的坑能绊倒一大半新手。它依赖PyTorch和MMCV,而MMCV又有cpu版和gpu版之分,版本对不上会导致无法编译或运行时崩溃。
推荐这样一套组合:Python 3.8 + PyTorch 1.10 + MMCV 1.4.8 + mmdetection 2.25.0。这个组合经过大量项目验证,稳定性好,坑相对少。如果要用更新的mmdetection 3.x,API变化较大,很多配置文件写法完全不同,对于想快速跑通项目的场景,还是建议从2.x入手。
MMCV的安装命令示例如下:
pip install mmcv-full==1.4.8 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10/index.html安装完mmcv之后,再安装mmdetection,从源码安装更推荐,因为可以方便地修改源码调试:
git clone https://github.com/open-mmlab/mmdetection.git cd mmdetection git checkout v2.25.0 pip install -r requirements/build.txt pip install -v -e .验证安装是否成功,跑一下官方demo:
python demo/image_demo.py demo/demo.jpg configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py如果看到检测结果图片输出,说明环境基本OK。要是卡在编译报错,八成是gcc版本或者CUDA版本的问题,建议先查PyTorch的CUDA版本是否和MMCV构建版本匹配。
3.2 配置文件解读与自定义修改
mmdetection的核心是配置文件,整个模型结构、训练参数、数据集路径都在一个config文件里管理。刚开始会觉得很绕,但搞清楚之后效率极高。
Faster-RCNN的基础配置路径一般是configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py。里面最关键的有几个部分:
数据集配置:
dataset_type = 'CocoDataset' data_root = 'data/wafer/' classes = ('scratch', 'particle', 'area_defect', 'edge_defect')注意classes的顺序必须和标注文件里的类别顺序一致。COCO格式的JSON里类别的id从1开始,如果在classes里少写了某个类,训练时就会报"class not in categories"之类的错误。
训练流水线配置:
train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True), dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), dict(type='RandomFlip', flip_ratio=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']), ]如果是用DataAugmentation-ForObjectDetect做过离线增强,这里的在线增强可以简单一点;如果期望在线增强,可以加入自定义的pipeline模块,在LoadAnnotations之后插入。
anchor配置:
anchor_generator=dict( type='RPNAnchorGenerator', scales=[2, 4, 8, 16, 32], ratios=[0.5, 1.0, 2.0], strides=[4, 8, 16, 32, 64])晶圆缺陷往往是小目标,比如划痕宽度只有十几个像素,颗粒污染可能就几个像素。如果anchor的最小scale还是默认的32,小缺陷根本不会被RPN捕捉到。项目里通常要增加小尺寸anchor,比如把scales调整成[1, 2, 4, 8, 16],并把strides对应往前移,让浅层特征图也能匹配小目标。这一步对检测小缺陷影响很大,值得反复实验。
3.3 训练启动与模型收敛判断
配置改好之后,训练命令如下:
python tools/train.py configs/faster_rcnn/faster_rcnn_r50_fpn_1x_wafer.py --work-dir work_dirs/wafer如果是小数据集(几百张图),建议用迁移学习,加载COCO预训练权重:
python tools/train.py 上述配置 --cfg-options load_from='checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'有了预训练权重,模型收敛速度会快很多,最终精度也更高。在小样本工业数据集上从头训,很容易陷入局部最优解。
在训练过程中关注两个信息:loss曲线的下降趋势和验证集mAP。如果loss下降但mAP波动很大,大概率是过拟合或者数据集本身有问题;如果loss像过山车一样剧烈震荡,需要降低学习率,建议从0.002降到0.0005左右再看看效果。
4. 实操过程与核心环节实现
4.1 数据增强流水线的具体实现
DataAugmentation-ForObjectDetect的使用方式比较灵活,既可以作为离线增强工具预处理数据,也可以作为在线增强库集成训练流程。我推荐的做法是先离线增强,把数据集扩大3到5倍,训练时在线增强只用轻度的翻转和色彩调整。
离线增强的核心优势是:可以直接查看增强后的图片和标注框是否正确,如果坐标映射出了问题,早发现早修正。在线增强出了问题,排查起来更麻烦。
使用DataAugmentation-ForObjectDetect的关键代码片段:
from data_augmentation_ForObjectDetect import DataAugmentation # 实例化增强器,可传入多种变换的配置 aug = DataAugmentation( rotation=True, rotation_angle=90, flip=True, brightness=True, contrast=True, scale=True, scale_factor=(0.8, 1.2) ) # 读取原图和标注数据 image = cv2.imread('wafer_001.png') # BGR格式 bboxes = [[x1, y1, x2, y2], ...] # 原始标注框 labels = [1, 2, 1, ...] # 对应类别id # 执行增强,返回变换后的图像和坐标 new_img, new_bboxes, new_labels = aug.execute(image, bboxes, labels)这里最关键的是execute方法返回的new_bboxes已经经过坐标变换,可以直接用于后续的格式转换和模型训练。如果增强后的框坐标出现负数或超出图像边界,需要在后续处理中将其裁剪或过滤掉,否则训练时会有莫名其妙的错误。
4.2 COCO格式标注生成脚本
因为离线增强得到的是文件夹里的图片和对应的txt或xml标注,要训练mmdetection,最好还是做一步转换,把标注统一成COCO格式。这个转换脚本不难写,核心结构如下:
import json import os from PIL import Image def create_coco_annotation(img_dir, label_files, output_json): images = [] annotations = [] categories = [ {"id": 1, "name": "scratch"}, {"id": 2, "name": "particle"}, {"id": 3, "name": "area_defect"}, {"id": 4, "name": "edge_defect"} ] ann_id = 1 for img_id, (img_name, label_file) in enumerate(zip(img_names, label_files)): img_path = os.path.join(img_dir, img_name) w, h = Image.open(img_path).size images.append({ "id": img_id + 1, "file_name": img_name, "width": w, "height": h }) for line in open(label_file): class_id, x1, y1, x2, y2 = parse_line(line) annotations.append({ "id": ann_id, "image_id": img_id + 1, "category_id": class_id, "bbox": [x1, y1, x2 - x1, y2 - y1], "area": (x2 - x1) * (y2 - y1), "iscrowd": 0 }) ann_id += 1 with open(output_json, 'w') as f: json.dump({"images": images, "annotations": annotations, "categories": categories}, f)有一点要特别注意:COCO格式的bbox是[x, y, width, height],不是[x1, y1, x2, y2]。新手经常在这里踩坑,用VOC格式的坐标直接塞进去,导致训练时mAP为0但loss还正常下降,排查半天找不到原因。
4.3 模型训练与评估跑通
准备完数据和配置之后,整个训练流程跑起来大约需要以下步骤:
- 配置
data/wafer/annotations/instances_train.json、instances_val.json和数据目录结构。 - 修改config中
data_root、classes、num_classes等字段。 - 指定
load_from为COCO预训练权重。 - 启动训练,观察前几个iter的loss是否在下降。
- 训练完成后用
tools/test.py评估mAP:
python tools/test.py 配置 --work-dir work_dirs/wafer训练一轮后,看各类别的AP分布。如果整体AP都不高,先别急着调模型,回到数据增强和标注质量上找问题;如果只有特定类别AP低,优先考虑该类别的样本量和标注一致性。
4.4 C++ ONNX模型部署的边界
项目后期如果要上产线,通常在C++环境用ONNX Runtime做推理部署。训练好的PyTorch模型需要先转成ONNX:
python tools/deployment/pytorch2onnx.py 配置 权重 --output-file wafer_faster_rcnn.onnx --input-img test.png --shape 800 1333导出ONNX有一个痛点:Faster-RCNN属于两阶段模型,包含了RPN和ROI Head,导出时会把NMS等后处理模块也带进去。ONNX Runtime支持这些算子的程度不一,经常出现某个算子不兼容的情况,需要反复调整。
更稳妥的做法是:把ONNX当作特征提取器,RPN的输出和ROI Head的输出分别拿到后处理里用C++自己实现NMS。虽然工作量多一点,但可控性强。整个部署链路一般要预留2到3天时间,不要指望一天搞定。
5. 常见问题与排查技巧实录
5.1 训练不收敛的排查清单
没有人能一次把检测模型训好,但下面这几个问题几乎每个人都遇到过:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| loss不下降 | 学习率过大/标签错误 | 降低学习率,检查标注框是否为空、类别id是否越界 |
| mAP始终为0 | 数据集格式错误或类别映射错误 | 检查bbox格式是否为xywh,classes顺序是否匹配JSON |
| 显存溢出(OOM) | 图像尺寸过大或batch size过大 | 降低batch size,缩小输入分辨率 |
| loss下降但AP低 | 数据量不足或标注质量差 | 加强数据增强,重新筛选错标框 |
| 训练正常但验证掉点 | 过拟合或数据分布不一致 | 增加正则化,检查train/val划分是否重叠 |
5.2 数据增强强度过大的警示
增强不是越多越好。我见过一个项目,把旋转角度设为任意值,导致晶圆图像里的圆形结构被旋转得失去物理意义,模型学到了扭曲后的错误特征,AP反而下降。
晶圆表面有固定的同心圆结构,如果随意旋转任意角度,这些结构的几何关系会被破坏,模型看到的是"不存在的缺陷形态"。所以建议旋转只保留90度、180度、270度这样的整数倍角度,保证几何意义不被破坏。彩色图像可以放心做色彩扰动,但灰度图像做太强的对比度变化也可能引入伪影。
调增强策略时盯住一个指标:验证集的AP变化。增强是为了提升验证集表现,如果加了某种增强后AP不升反降,果断去掉。
5.3 工业部署时的易忽略细节
模型训练完只是起点,真正的考验在上产线。几个容易忽略的细节:
- 输入图像尺寸不一致:训练时用Resize统一样式,但线上相机输出的分辨率可能不同,推理前要按相同方式resize,否则精度会掉。
- 缺陷类别在部署时合并:有时产线不需要细分scratch和particle,只需要判断"有缺陷/无缺陷"。可以在后处理里把多类合并成二类,减少误报。
- 推理耗时:Faster-RCNN在GPU上跑单张图一般20到40毫秒,CPU上可能要几百毫秒。如果产线节拍要求低于100毫秒,建议考虑TensorRT加速。
6. 项目复盘与扩展方向
把整个项目跑完之后,最大的体会是:这类工业检测项目的成功与否,七分在数据,三分在模型。Faster-RCNN本身是一个非常成熟的模型,mmdetection也把训练流程封装得很标准,真正拉开差距的是数据标注的质量、增强策略的合理性以及对业务场景的理解。
从扩展角度看,这个项目有几个可以深挖的方向。如果想提升小缺陷的检出率,可以尝试引入注意力机制模块或者用Cascade R-CNN替代Faster-RCNN,在ROI阶段做多级检测,对小目标更友好。如果数据量进一步增加,可以尝试Swintransformer这类更强的backbone,把特征提取能力再往上拉一档。如果要进一步压低延迟,可以把backbone从ResNet改成更轻量的MobileNetV3,代价是少量精度损失,换来的推理速度提升在产线上相当值得。
最后说一个小技巧:训练完成后把错误预测的样本可视化出来,把漏检和误检的图片打印出来,逐个看模型到底"看到了什么"。这一步能帮助你快速定位数据问题,而不是盲目调参。很多你以为的模型问题,最后看图才发现是标注框不准确或者类别定义有歧义。找一个周末,抱着图一张张过一遍,效果比盲试十组超参数都明显。
本文还有配套的精品资源,点击获取