工业机器视觉-基于深度学习的托盘PCB识别
工业机器视觉
工业机器视觉是指在制造业和工业环境中使用计算机视觉技术来执行检测、测量、识别和控制任务。它结合了硬件(如相机、镜头、光源)与软件(图像处理算法)来自动完成传统上需要人工视觉的任务,从而提高生产效率、产品质量以及工作安全性。工业机器视觉系统通常具有高精度、高速度和高可靠性,能够适应恶劣的工作环境。
应用领域
-
质量控制:
- 缺陷检测:检查产品表面是否有划痕、裂纹等缺陷。
- 尺寸测量:精确测量产品的尺寸是否符合标准。
- 色彩一致性:确保产品颜色的一致性。
-
装配验证:
- 确保组件正确安装,比如螺丝是否拧紧、部件是否对齐等。
- 检查包装完整性,确保所有零件都已放入包装内。
-
机器人引导:
- 通过视觉系统定位物体,引导机器人进行精确的拾取和放置操作。
- 实现自动化装配线上的精准定位。
-
条码/二维码读取:
- 用于跟踪产品从生产到销售的整个过程。
- 自动化仓库管理中的物品识别。
-
OCR(光学字符识别):
- 读取并解析标签、序列号等信息。
- 用于文档数字化过程中文字内容的提取。
-
安全监控:
- 监控生产线的安全状况,防止意外发生。
- 保障员工安全,例如通过监视危险区域内的活动。
关键技术
- 图像采集:高质量的相机和适当的照明条件是获取清晰图像的关键。
- 图像处理:包括预处理(如去噪、增强对比度)、特征提取(边缘检测、形状分析等)及模式识别。
- 决策制定:基于处理后的数据做出判断或采取行动,如分类、排序等。
- 集成与控制:将视觉系统与其他生产设备(如PLC、机器人等)集成,实现自动化流程。
优势
- 提高效率:减少人工干预,加快生产速度。
- 提升质量:减少人为错误,提高产品质量。
- 降低成本:长期来看,可以降低人力成本和因质量问题导致的成本。
- 改善工作条件:减少工人接触危险环境的机会。
随着技术的发展,尤其是深度学习技术的进步,工业机器视觉的能力正在不断增强,能够处理更加复杂多变的情况,为工业生产的智能化提供了强有力的支持。
项目背景
在中小规模的PCB(印制电路板)制造企业中,产品完成生产测试后的包装入库环节通常依赖于人工进行物料检查和摆放。这一过程中存在因人为因素导致的错误,如物料遗漏或摆放错误(例如Tray盘中的某个位置缺少物料、产品正反面放置错误等),这些问题可能会严重影响最终产品的质量以及客户的验收结果。为了解决上述问题,引入机器视觉技术成为一种有效的解决方案。
通过使用高精度摄像头采集图像,并结合先进的图像处理算法,可以实现对料盘中物料状态的自动化检测,快速准确地识别出缺料、错位等情况,从而显著提高包装前的质量控制水平,减少人为错误,确保产品质量符合标准。
项目需求
-
自动化检测流程:
- 人工上料与摆盘:由操作员手动将物料摆放至Tray盘。
- 送检:操作员将装有物料的Tray盘送至摄像设备下方进行检测。
- 自动检测:使用高精度摄像头对Tray盘进行图像采集,并利用机器视觉技术快速识别出哪些位置存在缺料或摆放错误的情况。
-
物料规格:
- 每个Tray盘包含50个产品单元。
- Tray盘的尺寸相对固定,以确保检测算法能够准确地定位每一个产品的位置。
- 每个产品单元种类繁多
-
检测功能要求:
- 缺料检测:系统应能快速且准确地识别Tray盘中缺失物料的具体位置。
- 错料检测:系统还应具备辨别产品是否被错误放置(例如正反面颠倒)的能力。
- 实时显示结果:检测完成后,系统应在显示屏上即时显示出缺料和错料的具体位置及其数量,以便操作员及时采取纠正措施。
-
性能指标:
- 检测速度:系统应当能够在短时间内完成对单个Tray盘的全面检测,以适应生产线的速度要求。
- 准确性:检测结果必须具有高度的准确性,以减少误报和漏报的概率。
- 通用性:PCB种类繁多,而且摆盘时方向不固定,必须保证兼容所有PCB产品类型和各个方向的摆放方式
- 易用性:用户界面友好,便于操作人员理解和使用。
通过实施上述解决方案,可以显著提升PCB生产线上物料检查环节的效率和可靠性,从而保证产品质量,满足客户高标准的要求。
需求分析
相机及镜头
由于料盘尺寸较固定,并且不需要对PCB产品进行缺陷检测,所以相机、镜头不需要选择高配置的,在合适的视野范围下,能全部看到料盘即可,对像素高低要求也不高。30万像素,分辨率640*480,可变焦普通工业相机。
光源
不需要特殊的打光,普通的条形光源即可。
检测识别
由需求分析可判定为分类任务,只需要将每个位置的PCB图片进行分类、统计数量即可。但是由于料盘中产品种类繁多,方向不一致,所以首先需要收集样本数据。然后使用深度学习技术进行训练,最后预测得到分类结果即可。
数据收集
为了减少样本数据数量,也要保证训练数据足够多和全面的情况下,我们只采集了20种规则的样品图片,每种规格样品正反各一张,总共40张样品图片数据。然后以这些样本图片为基础,生成上万张训练图片(使用OpenCV,在光照、旋转方向上进行变化)。
某种规格的一个样本示例:
import os
import cv2
import numpy as np
import random
from tqdm import tqdm
def rotate_img(img, angle):
(h, w) = img.shape[:2]
center = (w // 2, h // 2)
scale = 1.0
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(img, M, (w, h), flags=cv2.INTER_NEAREST, borderMode=cv2.BORDER_REPLICATE)
return rotated
def create_pcb_images():
# 采集的图片中指定区域,包含一个PCB模块
pt1 = (272, 210)
pt2 = (328, 245)
# 生成的图片保存路径
for file in tqdm(os.listdir('images_pcb')):
file_path = os.path.join('images_pcb', file)
os.remove(file_path)
# 遍历采集的样本图片路径
for image_name in tqdm(os.listdir('images_src')):
image_path = os.path.join('images_src', image_name)
img = cv2.imread(image_path)
# 取出目标区域,也就是需要变换的区域图片
pcb_img = img[pt1[1]:pt2[1], pt1[0]:pt2[0]]
for i in range(5, 360, 5):
# 旋转
rotated_img = rotate_img(pcb_img, i)
name = image_name.replace('.jpg', '')
cv2.imwrite(f'images_pcb/{name}-{i}.jpg', rotated_img)
# 亮度变化
for j in range(10, 100, 10):
brightness_img = cv2.convertScaleAbs(rotated_img, alpha=1.5, beta=j)
cv2.imwrite(f'images_pcb/{name}-{i}-{j}.jpg', brightness_img)
if __name__ == '__main__':
create_pcb_images()
旋转和亮度变换可根据实际情况调整。
拆分训练数据和验证数据:
import os
import random
import shutil
from tqdm import tqdm
if __name__ == '__main__':
ok_dir = r'images\OK'
ng_dir = r'images\NG'
for file in tqdm(os.listdir(ok_dir)):
os.remove(os.path.join(ok_dir, file))
for file in tqdm(os.listdir(ng_dir)):
os.remove(os.path.join(ng_dir, file))
for file in tqdm(os.listdir(r'train\OK')):
os.remove(os.path.join(r'train\OK', file))
for file in tqdm(os.listdir(r'train\NG')):
os.remove(os.path.join(r'train\NG', file))
for file in tqdm(os.listdir(r'val\OK')):
os.remove(os.path.join(r'val\OK', file))
for file in tqdm(os.listdir(r'val\NG')):
os.remove(os.path.join(r'val\NG', file))
data_path = 'images_pcb'
data_files = os.listdir(data_path)
for file in tqdm(data_files):
if file.find('_f') >= 0:
shutil.copyfile(os.path.join(data_path, file), os.path.join(ok_dir, file))
else:
shutil.copyfile(os.path.join(data_path, file), os.path.join(ng_dir, file))
ok_files = os.listdir(ok_dir)
ng_files = os.listdir(ng_dir)
random.shuffle(ok_files)
random.shuffle(ng_files)
ok_count = int(len(ok_files) * 0.9)
for i in tqdm(range(ok_count)):
shutil.copyfile(os.path.join(ok_dir, ok_files[i]),
os.path.join(r'train\OK', ok_files[i]))
for i in tqdm(range(ok_count, len(ok_files))):
shutil.copyfile(os.path.join(ok_dir, ok_files[i]),
os.path.join(r'val\OK', ok_files[i]))
ng_count = int(len(ng_files) * 0.9)
for i in tqdm(range(ng_count)):
shutil.copyfile(os.path.join(ng_dir, ng_files[i]),
os.path.join(r'train\NG', ng_files[i]))
for i in tqdm(range(ng_count, len(ng_files))):
shutil.copyfile(os.path.join(ng_dir, ng_files[i]),
os.path.join(r'val\NG', ng_files[i]))
目录结构如下:
NG、OK就是分类类别,可根据实际需求修改
训练(Ultralytics YOLO)
基于Ultralytics YOLO(Home - Ultralytics YOLO Docs)的YOLOv8-cls分类模型来进行训练、预测。下面简单描述一下过程:
- 下载训练框架:ultralytics/ultralytics at main · ultralytics/ultralytics · GitHub
- 在ultralytics目录下创建datasets文件夹,然后在datasets下创建工程文件夹,并且准备样本数据图片
- 执行create_more_images.py进行数据增强,扩充训练数据集
- 执行split_train_val.py进行数据拆分,拆分为训练数据集和测试数据集
- 在ultralytics目录下创建train.py并执行脚本
from ultralytics import YOLO
if __name__ == '__main__':
model = YOLO('cfg/models/v8/yolov8s-cls.yaml').load('weights/yolov8s-cls.pt')
model.train(data='datasets/tray-pcb', epochs=100, imgsz=64, task='classify', batch=64,
device=0, amp=False, patience=10, close_mosaic=30)
- 训练完成后(可提前停止),会在runs文件夹下生成classify目录,里面包含每次开启训练任务时的训练数据、过程、结果、模型文件.pt
预测
from ultralytics import YOLO
img_path = 'assets/pcb-init.jpg'
model = YOLO('runs/classify/train/weights/best.pt')
model.predict([img_path], imgsz=64, verbose=True)
for result in results:
print(result.names)
print('----------------------------')
print(result.probs.top1)
print('----------------------------')
上位机
基于PyQt5开发一个简单的上位机,实时显示分类检测结果即可。