1. 项目背景与核心需求
在工业生产线上,产品表面污渍检测一直是个让人头疼的问题。传统的人工目检方式不仅效率低下,而且容易因视觉疲劳导致漏检。我在某家电制造企业实习时就亲眼见过,质检员每天要检查上千个金属面板,到下午三四点的时候,漏检率能飙升到15%以上。
这个毕设项目就是要用CNN(卷积神经网络)来解决这个痛点。具体来说,我们需要开发一个能自动识别产品表面是否有污渍的智能系统。这里的关键在于:
- 识别对象:可以是金属件、塑料件、纺织品等各种材质
- 污渍类型:包括油渍、灰尘、锈迹等常见污染物
- 应用场景:工业质检流水线、产品出厂前终检等
实际项目中我发现,不同材质的反光特性会极大影响识别效果。比如不锈钢表面的油渍和亚克力板上的指纹,需要的处理策略完全不同。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术方案设计
2.1 整体架构
经过多次迭代,最终确定的系统架构包含三个核心模块:
-
图像采集层
- 使用200万像素工业相机(实际测试发现低于这个分辨率会影响细小污渍识别)
- 配合环形LED光源消除反光干扰
- 图像采集频率与传送带速度同步(这个需要现场调试)
-
算法处理层
- 基于PyTorch框架搭建CNN模型
- 预处理包括:灰度化、直方图均衡化、高斯滤波
- 核心网络采用改进版ResNet18
-
结果输出层
- 通过Modbus TCP协议与PLC通信
- 不良品触发气动剔除装置
- 实时显示检测结果和统计报表
2.2 关键参数选择
在模型训练过程中,有几个参数需要特别注意:
- 输入图像尺寸:经过测试,480×480像素是最佳平衡点
- 太大(如800×800)会导致推理速度下降
- 太小(如224×224)会丢失细节特征
- 批量大小(batch size):根据GPU显存选择
- GTX 1660 Ti建议用16
- RTX 3060可以用到32
- 学习率:采用余弦退火策略
- 初始值0.001
- 最小0.0001
3. 核心算法实现
3.1 数据预处理
真实工业场景的数据处理比想象中复杂得多。我的数据集来自三家不同工厂的生产线,需要统一处理:
python复制def preprocess_image(img):
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
equalized = clahe.apply(gray)
# 高斯滤波去噪
blurred = cv2.GaussianBlur(equalized, (5,5), 0)
# 归一化
normalized = blurred / 255.0
return normalized
特别注意:不同厂家的相机色彩空间可能不同,一定要先做白平衡校准!
3.2 CNN网络结构
在ResNet18基础上做了三点改进:
- 输入层:改用单通道输入(灰度图)
- 第一个卷积层:kernel_size从7改为5,更适合小尺寸污渍
- 最后全连接层:添加Dropout(0.5)防止过拟合
python复制class CustomResNet(nn.Module):
def __init__(self):
super().__init__()
original = resnet18(pretrained=True)
# 修改第一层卷积
self.conv1 = nn.Conv2d(1, 64, kernel_size=5, stride=2, padding=2, bias=False)
# 复用其他层
self.bn1 = original.bn1
self.relu = original.relu
self.maxpool = original.maxpool
self.layer1 = original.layer1
self.layer2 = original.layer2
self.layer3 = original.layer3
self.layer4 = original.layer4
self.avgpool = original.avgpool
# 修改全连接层
self.fc = nn.Sequential(
nn.Dropout(0.5),
nn.Linear(512, 2)
)
4. 训练技巧与调优
4.1 数据增强策略
工业场景的数据增强需要特别考虑实际情况:
- 有效增强方式:
- 随机旋转(-5°到+5°)
- 亮度调整(±20%)
- 添加高斯噪声
- 需要避免的方式:
- 大角度旋转(产品在传送带上不会倒置)
- 颜色变换(会改变污渍特征)
- 裁剪(会丢失边缘污渍)
python复制train_transform = transforms.Compose([
transforms.RandomRotation(5),
transforms.ColorJitter(brightness=0.2),
transforms.Lambda(lambda x: x + torch.randn_like(x)*0.01),
transforms.ToTensor()
])
4.2 损失函数选择
尝试过三种损失函数后,发现Focal Loss最适合这个场景:
- CrossEntropyLoss:普通污渍效果尚可,但细小污渍识别率低
- DiceLoss:容易过拟合
- FocalLoss(γ=2):对小目标检测效果提升明显
实现代码:
python复制class FocalLoss(nn.Module):
def __init__(self, gamma=2):
super().__init__()
self.gamma = gamma
def forward(self, inputs, targets):
BCE_loss = F.cross_entropy(inputs, targets, reduction='none')
pt = torch.exp(-BCE_loss)
loss = (1-pt)**self.gamma * BCE_loss
return loss.mean()
5. 部署优化技巧
5.1 模型量化
为了让模型能在边缘设备运行,需要进行量化:
python复制model = CustomResNet().eval()
quantized_model = torch.quantization.quantize_dynamic(
model,
{nn.Linear, nn.Conv2d},
dtype=torch.qint8
)
实测效果:
- 模型大小:从45MB减小到11MB
- 推理速度:从120ms提升到65ms
- 准确率下降:仅降低0.3%
5.2 多线程处理
工业场景需要处理高帧率视频流,我的解决方案:
python复制import queue
from threading import Thread
class Processor:
def __init__(self):
self.input_queue = queue.Queue(maxsize=10)
self.output_queue = queue.Queue(maxsize=10)
def start_workers(self):
Thread(target=self._capture_thread).start()
Thread(target=self._inference_thread).start()
Thread(target=self._output_thread).start()
def _capture_thread(self):
while True:
frame = camera.get_frame()
self.input_queue.put(frame)
def _inference_thread(self):
while True:
frame = self.input_queue.get()
result = model(frame)
self.output_queue.put(result)
def _output_thread(self):
while True:
result = self.output_queue.get()
plc.send(result)
6. 常见问题排查
6.1 识别率突然下降
现象:上午运行正常,下午识别准确率下降20%
可能原因:
- 车间光照变化(窗户阳光直射)
- 相机镜头污染
- 传送带速度变化
解决方案:
- 加装遮光罩
- 设置定时镜头清洁提醒
- 在图像预处理中添加亮度自动校正
6.2 模型误检特定图案
现象:将产品上的条形码识别为污渍
解决方法:
- 在数据集中添加条形码样本作为负样本
- 在预处理中增加条形码区域检测屏蔽
- 调整非极大值抑制(NMS)参数
7. 性能优化记录
经过多次优化后的最终指标:
| 优化阶段 | 准确率 | 速度(fps) | 显存占用 |
|---|---|---|---|
| 初始版本 | 92.1% | 8.3 | 3.2GB |
| +数据增强 | 94.7% | 7.8 | 3.2GB |
| +FocalLoss | 96.2% | 7.8 | 3.2GB |
| 量化后 | 95.9% | 15.2 | 1.1GB |
| 多线程 | 95.9% | 23.5 | 1.1GB |
这个项目最让我意外的是,简单的灰度图处理反而比RGB三通道效果更好。后来分析发现,彩色信息在污渍检测中反而会引入噪声,特别是当不同批次的原材料颜色有细微差别时。这也提醒我,工业场景的算法设计一定要结合实际物理特性,不能盲目套用通用方案。
