工业AI落地_01_AI视觉检测晶圆缺陷识别_20260815
工业AI落地_01_AI视觉检测晶圆缺陷识别_20260815
1. 问题背景:人工目检这活儿,真不是人干的
我是2021年进的华东那家12寸封测厂,刚去的时候被安排到终检工段,干的活就是盯着AOI(自动光学检测)设备吐出来的图,再人工复判。现在回头看,那段日子把我对制造业苦的理解直接拉满了。
先说产线的基本情况:我们那条线月产大概8万片晶圆,AOI设备扫完之后,所有被判可疑的片子都要人再去看一遍。一开始厂里配了15个目检工,三班倒,每人每天理论上最多能看800片。听起来不少,但架不住夜班。凌晨两三点,人盯着高亮屏幕上直径300毫米的晶圆图,找几微米级别的划伤和颗粒,看半小时眼睛就花了。
真正的麻烦不是慢,是漏。我们后来做了一次内部抽查,把已经过人工目检放行的片子再拿电子显微镜复检,发现漏检率大概在1.2%到1.8%之间浮动,夜班比白班高出接近一倍。别小看这百分之一点几,一次客户端因为颗粒缺陷流出导致的整批退货,赔的钱够发那15个人半年工资。
有人会说:那不是有AOI吗?问题就在这——AOI的误报率高得离谱,原始误报率能到30%。也就是说它报的可疑里,十个里有七个是假的。所以AOI非但没把人替掉,反而制造了一大堆需要人去复判的活。老板一度想砸钱把AOI灵敏度调低,结果灵敏度一低,漏检更严重。这是个死结。
我那时候就在想,既然AOI能拍出图,人能判断,那中间这层人眼判断能不能用模型顶上?这就是后面整个项目的出发点。但先说结论:不是简单买个深度学习模型装上就行,里面的坑比晶圆上的缺陷还多。
顺便说句成本账,这也是老板最关心的。15个目检工,按我们当地薪资加社保,一年人力成本小两百万。再加上质量索赔、客户端审计扣分带来的订单风险,光这一项每年隐性损失就不低于三百万。所以老板不是不想上AI,是怕上错了——市面上讲AI检测的故事太多了,能稳定跑在产线上的太少。后来我跟他拍胸脯说先灰度跑两个月看数字,他才批了预算。这个用数据换信任的思路,后面我会反复提,因为它决定了项目能不能活下来。
还有个背景很多人忽略:我们的客户是车规级芯片厂,对缺陷零容忍,审厂时连目检工的培训记录、复判一致性都要查。人工目检最大的软肋就是一致性差——同一个缺陷,A工判异常、B工判正常的情况时有发生,这种主观波动在车规 audit 里是扣分项。所以上AI不只是省钱,更是为了把判定标准锁死,让每一片都按同一把尺子量。
2. 技术原理:为什么是 OpenCV + CNN 的两段式,而不是端到端一把梭
最开始我试过最直接的思路:把整张晶圆图(500万像素)直接塞进ResNet50做分类。想法很朴素——深度学习不是啥都能学吗?结果狠狠挨了一巴掌。
第一,整图太大,一张图直接推理要200毫秒往上,产线节拍是秒级的,根本扛不住。第二,也是更致命的,缺陷在整图里占比极小,平均下来连万分之一都不到,端到端网络根本看不见那点信号,训练出来就是个永远判正常的废物。
后来定的方案是两段式:先用传统计算机视觉(OpenCV)把候选缺陷区域(ROI)抠出来,再用一个轻量的CNN对ROI做精细分类。这个分工的逻辑是——ROI提取不需要多聪明,用规则就能砍掉99%以上的正常区域;难的是在抠出来的小图上判断这到底是划伤还是颗粒还是正常噪点,这才是CNN该干的活。
OpenCV那一段我们做了这几件事:先在明场和暗场两种成像下分别处理(划伤在暗场下对比度更高,颗粒在明场下更明显);然后高斯滤波去噪,再用自适应阈值分割出候选区域;接着上形态学的开闭运算把孤立噪点抹掉;最后用轮廓的面积、长宽比、圆形度做一道硬筛选,把面积太小(像sensor坏点)和太大(像整片脏污)的剔除。
CNN那一段,输入是64×64的灰度ROI,做五分类:正常、划伤、颗粒、图形缺陷、污渍。这里的关键不是网络多深,而是两件事:一是轻量,我们最后用的就是一个四层卷积加全局池化的小网络,推理18毫秒,能塞进产线工控机;二是数据不均衡的处理——实际产线上颗粒和划伤样本多,图形缺陷和污渍极少,直接训练网络会偏向多数类,所以我们上了Focal Loss,再配合难例挖掘,专门盯着分错的样本反复练。
还有个细节值得说:我们没有把ROI图当纯分类,而是额外加了一个边缘梯度特征分支,因为颗粒和污渍在成像上太像了,靠像素分类容易混,但颗粒边缘锐利、稳定,污渍边缘糊、渐变,这个物理区别帮我们把这两类的混淆率从12%压到了3%以下。
为什么输入固定成64×64灰度而不是彩色?一个重要考量是推理速度和设备负担。彩色三通道意味着三倍的算量,而晶圆缺陷在灰度下对比度反而更清晰,没必要为那点颜色信息付出实时性的代价。我们做过对比,彩色输入在准确率上只比灰度高0.3个点,但推理慢了近一倍,产线不买账,最后砍了。
数据增强那块也值得多说两句。实际产线里图形缺陷和污渍样本极少,直接训练网络会严重偏向多数类。我们除了常规旋转、亮度抖动,还加了弹性形变(elastic distortion),模拟晶圆在传送带上轻微的拉伸和畸变,让模型对位置不敏感。另外用了在线难例挖掘:每个epoch把分错的样本挑出来,下一轮重点练,相当于让模型自己出题考自己。这套组合拳下来,少数类的召回率从70%出头拉到了90%以上。
3. 实战案例:上线前踩的三个坑,每一个都差点让项目黄了
光讲原理没意思,说说真刀真枪落地时的破事。整个项目从立项到全量上线跑了差不多9个月,中间有三个坑我到现在都记得。
坑一:推理太慢,产线节拍不让。就像前面说的,一开始我偷懒上了ResNet50,在办公室的显卡上跑得飞起,一到产线那台只有核显的工控机,一张图200毫秒,整线直接堵死。解决办法不是堆硬件(老板不给钱),而是把网络砍成自研轻量CNN,参数量从2300万降到不到90万,推理降到18毫秒,代价是Top-1准确率从92%掉到89%,但配合后面的复检机制完全能接受。
坑二:颗粒和污渍分不清。灰度图里这两类有时候就是亮度不同的小块,模型一开始把它们当成一伙的,混淆率12%。我们翻了一周误判样本才发现问题:颗粒是外来异物,边缘特别锐利;污渍是工艺残留,边缘是渐变的。于是加了边缘梯度统计作为辅助特征,这一招比换大模型管用多了。
坑三:微划伤漏检。小于5个像素的划伤,暗场成像下对比度也低,模型基本看不见。最后的解法是成像端配合——把暗场光源角度调了15度,让划伤的阴影更明显,再在预处理里加一道局部对比度增强。这给我一个教训:视觉检测的 ceiling 很多时候不在算法,在成像。
上线策略上我们也没犯傻:没有一上来就撤掉人工,而是灰度运行了两个月,AI和人工并行判同一批片子,每天比对差异。到了第二个月底,AI在漏检指标上已经稳定优于人工,我们才逐步把人工转到复检AI报的可疑项和做异常处理上,从15人降到4人。
有个细节我印象特别深:某天夜班AI连续报了3片划伤,当班的老大哥肉眼看了三遍说没问题,差点当成误报放行。我第二天拿来用电子显微镜一打,确实是3到5微米的微划伤,肉眼在屏幕上真看不出来。那一次算是彻底让产线信了AI。
还有个容易被忽略的环节:数据标注。我们前三个月攒了2.3万张ROI,但标注不是找几个实习生框框就完事。晶圆缺陷的标注需要懂工艺的人来定这到底算划伤还是颗粒,否则标错了模型学歪。我们拉着AOI设备商和厂内工艺工程师开了好几次会,统一了缺陷定义词典,才敢放手标。这一步慢,但后面模型训得顺,根子在这。
另外,和AOI上位机软件的对接也磨了很久。厂家原来的接口只吐整图,我们得让他们把坐标和缩略图也导出来,不然AI算完缺陷位置,复检工还得自己回去翻原图,体验极差。最后改成AI结果直接叠加在AOI界面上,复检工点一下就能看到缺陷框和置信度,接受度一下就上来了。
4. 完整代码:OpenCV 提取 ROI + CNN 分类(产线可跑通版)
下面这段代码是脱敏后的核心逻辑,去掉了厂内路径和模型密钥,但流程是真实跑在工控机上的。要点都在注释里:CLAHE 局部对比度增强是为了救微划伤,形态学开运算是为了抹噪点,面积硬筛选是为了砍掉 sensor 坏点。CNN 部分只贴了调用,网络结构是前面说的轻量四层卷积。代码行数控制在合理范围,方便嵌入到现有的 AOI 上位机软件里。需要提醒的是,extract_defect_roi 里那几个阈值(20、5000、31、10)都是在我们产线成像条件下调出来的,换设备或换成像参数要重新标定,不要原样照搬。
下面是当时在产线工控机上跑通的核心代码(已脱敏,去掉了厂内路径和密钥):
import cv2, numpy as np, os from tensorflow.keras.models import load_model # 1) OpenCV 做 ROI 提取与预处理(暗场对比度增强) def extract_defect_roi(img_path): img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) gray = clahe.apply(gray) # 局部对比度增强,救微划伤 blur = cv2.GaussianBlur(gray, (5,5), 0) thr = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 31, 10) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)) thr = cv2.morphologyEx(thr, cv2.MORPH_OPEN, kernel) contours, _ = cv2.findContours(thr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) rois = [] for c in contours: a = cv2.contourArea(c) if a < 20 or a > 5000: # 滤掉 sensor 坏点与整片脏污 continue x,y,w,h = cv2.boundingRect(c) rois.append((gray[y:y+h, x:x+w], (x,y,w,h))) return img, rois # 2) CNN 对 ROI 做五分类(正常/划伤/颗粒/图形缺陷/污渍) model = load_model('wafer_defect_cnn.h5') labels = ['正常','划伤','颗粒','图形缺陷','污渍'] for f in os.listdir('wafers'): img, rois = extract_defect_roi(os.path.join('wafers', f)) for roi, box in rois: r = cv2.resize(roi, (64,64)) / 255.0 p = model.predict(r[None,...,None], verbose=0) idx = int(np.argmax(p)) if labels[idx] != '正常': print(f, box, labels[idx], round(float(p[idx]),3))
5. 效果对比:数字不会骗人,但也别只看一个数字
项目全量上线运行半年后,我们拉了一份对比报告。最直接的两个指标:漏检率,从人工的1.5%左右降到了0.15%,降了整整十倍;AOI原始的误报率30%被我们压到了8%——注意,这里AI是替代了人工复判那一层,所以误报率指的是AI报可疑、人工复判其实正常的比例,8%意味着4个复检工基本不会被淹死。
速度上,单台工控机等效的检测能力是每人每天2400片,是人工的3倍。人力从15人降到4人,这4个人做的事也变了:不再是机械盯屏,而是处理AI标记的可疑项和设备异常,工作强度反而下来了。
质量损失这块最实在:因为缺陷流出导致的客户端投诉,从月均6起降到了0.5起左右。算经济账,硬件加开发一次性投入大概80万,每年省下的人力加质量损失约210万,回收期不到半年。
但我必须泼盆冷水,免得你以为这是银弹:AI的8%误报仍需人复检,深色污渍在暗场下偶尔还会误判,模型每隔一个季度因为光源老化和新品导入要重新校准一次。所以AI替代人工这个说法不准确,准确说是AI把人工从重复劳动里解放出来,去干更需要判断的活。
再补一个容易被老板误解的点:上线AI之后,质量不是一夜之间变好的,而是前两个月基本在校准信任。我们每天把AI判错的和人工判错的拉出来复盘,头一个月AI还有几次漏报,靠的就是和人工并行才没流出。所以任何想明天就撤掉目检的念头,都是拿质量冒险。稳健的做法是并行跑满一个季度,等漏检率连续达标再动人力。
从操作员的角度也得说句公道话:一开始复检工抵触得很,觉得这玩意儿抢饭碗。后来我们明确保留岗位、只调整工作内容,并且把AI报对的案例做成周报贴在车间,他们慢慢发现AI帮我挡了之前要背锅的漏检,态度就反转了。变革能不能推下去,往往不是技术问题,是人的问题。
最后说个细账:原来15个人三班倒,每月加班费是一笔不小的开销,而且目检工离职率高、招人难,常常空着岗靠别人顶。AI上线后这4个复检岗反而成了香饽饽——不用熬通宵盯屏,还能学设备,稳住了队伍。这对产线管理的隐性价值,比省下的工资单还实在。
6. 实施建议:给也想上视觉检测的朋友几条大实话





