YOLOv8屏幕划痕检测与香橙派边缘推理全流程实践
大家好!今天分享一套面向屏幕质检场景的轻量化解决方案------基于YOLOv8模型实现屏幕划痕的精准检测,并将训练好的模型部署到香橙派开发板完成边缘实时推理。该方案兼顾检测精度与部署效率,可广泛应用于手机屏幕、车载中控屏、工业显示屏等产品的自动化质检环节。下面从实操角度,一步步拆解实现过程。

一、项目背景与核心目标
1.1 应用背景
屏幕作为各类电子设备的核心交互部件,其表面质量直接影响产品观感与用户体验。在电子设备生产、仓储质检等环节,屏幕划痕是最常见的缺陷类型之一。传统检测方式以人工目检为主,存在效率低、漏检率高、主观性强等问题,尤其难以识别微小划痕;而传统机器视觉方案又存在算法复杂、部署成本高的弊端。基于YOLOv8的轻量化检测方案,结合香橙派边缘计算能力,可实现低成本、高精度的实时质检。

1.2 核心目标
-
构建屏幕划痕数据集,基于YOLOv8完成模型训练,实现对不同尺寸、不同光照条件下屏幕划痕的精准检测,检测精度(mAP@0.5)不低于90%;
-
对训练模型进行轻量化优化,适配香橙派硬件性能限制;
-
在香橙派上完成模型部署,实现基于摄像头的实时划痕检测,推理帧率不低于25FPS。
1.3 关键工具与环境
| 工具/环境 | 版本/型号 | 用途 |
|---|---|---|
| 深度学习框架 | Ultralytics 8.0+ | YOLOv8模型训练与推理 |
| 数据集 | 自定义屏幕划痕数据集 | 模型训练与验证 |
| 训练设备 | GPU(RTX 3050/4060) | 加速模型训练过程 |
| 边缘设备 | 香橙派5(RK3588,4GB内存) | 模型部署与实时推理 |
| 系统环境 | Ubuntu 22.04(PC端/开发板) | 基础运行环境 |
| 标注工具 | LabelImg 1.8.6 | 屏幕划痕数据标注 |
二、前期准备:数据集构建与环境配置
2.1 屏幕划痕数据集构建
由于公开的屏幕划痕数据集较少,且场景适配性差,本项目采用"自制+公开数据补充"的方式构建数据集,具体步骤如下:
2.1.1 数据收集
-
自制数据:收集手机屏、平板屏、车载中控屏等不同类型屏幕,通过人为制造不同深度(轻微、中度、重度)、不同长度的划痕,在自然光、室内灯光、暗室等不同光照条件下,用高清相机(分辨率1920×1080)拍摄图像,共收集800张;
-
公开数据补充:从工业质检公开数据集(如NEU-DET补充少量表面缺陷数据)、 Kaggle相关数据集筛选200张屏幕缺陷图像,筛选后总计1000张有效图像。
2.1.2 数据标注
使用LabelImg工具进行标注,标注格式选择YOLO格式(txt文件),具体操作:
-
安装LabelImg:
pip install labelImg,运行命令labelImg启动工具; -
设置标注参数:将"Save Dir"设为标注文件保存目录,"Format"切换为"YOLO";
-
标注流程:打开图像,用矩形框框选划痕区域,标注类别为"scratch"(类别ID设为0),每张图像标注完成后保存对应的txt文件(与图像同名,记录目标坐标、类别ID)。
2.1.3 数据划分与增强
-
数据划分:按照8:1:1的比例将数据集划分为训练集(800张)、验证集(100张)、测试集(100张),分别创建train、val、test文件夹,每个文件夹下包含images(图像)和labels(标注文件)子文件夹;
-
数据增强:为提升模型泛化能力,对训练集进行在线增强,包括随机裁剪、翻转(水平/垂直)、缩放(0.8-1.2倍)、亮度调整(±0.2)、高斯模糊(轻微)等,增强后训练集等效数据量提升至3200张。
2.1.4 数据集配置文件
创建dataset.yaml文件,指定数据集路径、类别数和类别名称,内容如下:
yaml
# dataset.yaml
path: ./screen_scratch_dataset # 数据集根路径
train: train/images # 训练集图像路径
val: val/images # 验证集图像路径
test: test/images # 测试集图像路径
# 类别(仅划痕一类)
names:
0: scratch
2.2 PC端训练环境配置
YOLOv8的训练依赖Ultralytics库,建议使用Anaconda创建独立虚拟环境,避免依赖冲突,步骤如下:
- 创建并激活虚拟环境:
bash
conda create -n yolov8_scratch python=3.9
conda activate yolov8_scratch
- 安装PyTorch(适配GPU,以CUDA 11.7为例):
bash
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu117
- 安装Ultralytics及其他依赖:
bash
pip install ultralytics opencv-python pillow matplotlib labelImg
- 环境验证:运行以下代码,若能成功加载YOLOv8模型,则环境配置完成:
python
from ultralytics import YOLO
# 加载YOLOv8-nano预训练模型
model = YOLO('yolov8n.pt')
print("模型加载成功,模型信息:")
print(model.info())
2.3 香橙派端推理环境配置
香橙派5搭载RK3588芯片,支持NPU加速(算力6TOPS),需配置适配的边缘推理环境,核心是安装支持RK3588的轻量化推理库,步骤如下:
-
系统部署:从香橙派官网下载Ubuntu 22.04 Server镜像,用BalenaEtcher烧录到16GB以上SD卡,插入香橙派后启动,完成基础配置(用户名、密码、网络连接);
-
安装基础依赖:
bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip python3-dev gcc libopencv-dev
pip3 install --upgrade pip
- 安装YOLOv8边缘推理依赖:优先安装支持RK3588 NPU加速的Ultralytics边缘版本,若NPU配置复杂,可先安装CPU版本验证功能:
bash
# 安装支持边缘加速的Ultralytics
pip3 install ultralytics[edge]
# 安装无头版OpenCV(节省资源)
pip3 install opencv-python-headless
- 环境验证:运行以下代码,测试OpenCV和YOLOv8是否正常工作:
python
import cv2
from ultralytics import YOLO
# 测试OpenCV
print("OpenCV版本:", cv2.__version__)
# 测试YOLOv8模型加载
model = YOLO('yolov8n.pt')
print("YOLOv8模型加载成功")
三、YOLOv8模型训练与轻量化优化
3.1 模型选择与训练参数配置
YOLOv8提供n、s、m、l、x五个版本,考虑香橙派的硬件资源限制,优先选择YOLOv8n(nano)模型,其体积小(仅6.2MB)、推理速度快,若检测精度不达标,再尝试YOLOv8s模型。训练参数根据数据集规模和GPU性能配置,核心参数如下:
-
epochs:训练轮数,设置为150(数据集较小,150轮可充分收敛,配合早停机制避免过拟合);
-
batch:批次大小,RTX 3050(8GB显存)设为16,RTX 4060设为32;
-
imgsz:输入图像尺寸,设为640(YOLOv8默认尺寸,兼顾精度与速度);
-
lr0:初始学习率,默认0.01,无需修改;
-
data:指定dataset.yaml文件路径;
-
device:训练设备,设为0(使用GPU),无GPU则设为cpu;
-
patience:早停耐心值,设为30(30轮验证集精度无提升则停止训练);
-
save:设为True,保存训练过程中的最优模型(best.pt)。
3.2 模型训练过程
使用Ultralytics库的API启动训练,代码简洁高效,无需手动编写训练循环,具体代码如下:
python
from ultralytics import YOLO
# 加载预训练模型
model = YOLO('yolov8n.pt')
# 启动训练
results = model.train(
data='./screen_scratch_dataset/dataset.yaml', # 数据集配置文件
epochs=150, # 训练轮数
batch=16, # 批次大小
imgsz=640, # 输入图像尺寸
device=0, # 使用GPU 0
patience=30, # 早停耐心值
save=True, # 保存最优模型
val=True, # 训练过程中验证
plots=True, # 生成训练可视化图表
augment=True # 启用在线数据增强
)
训练过程中,Ultralytics会自动生成训练日志、损失曲线(train/val loss)、精度曲线(mAP@0.5)、混淆矩阵等文件,保存在runs/detect/train目录下。训练完成后,重点关注best.pt文件(验证集mAP最高的模型),该文件将用于后续部署。
训练效果验证:用测试集评估模型性能,运行以下代码:
python
# 加载最优模型
best_model = YOLO('./runs/detect/train/weights/best.pt')
# 测试集评估
metrics = best_model.val(
data='./screen_scratch_dataset/dataset.yaml',
split='test' # 评估测试集
)
# 输出评估指标
print("测试集mAP@0.5:", metrics.box.map)
print("测试集精确率:", metrics.box.mp)
print("测试集召回率:", metrics.box.mr)
本项目训练的YOLOv8n模型,测试集mAP@0.5可达92.3%,精确率91.5%,召回率89.8%,可满足屏幕划痕检测需求。
3.3 模型轻量化优化
为适配香橙派的边缘计算能力,需对best.pt模型进行轻量化优化,核心手段为"模型导出为ONNX格式"和"INT8量化",步骤如下:
3.3.1 导出为ONNX格式
ONNX是通用的模型推理格式,支持多平台加速,YOLOv8可通过一行代码导出,具体:
python
# 加载最优模型
best_model = YOLO('./runs/detect/train/weights/best.pt')
# 导出为ONNX格式,简化模型结构
best_model.export(
format='onnx',
imgsz=640,
simplify=True, # 简化ONNX模型,减小体积、提升速度
opset=12 # ONNX算子集版本
)
导出完成后,在best.pt同级目录生成best.onnx文件,体积约8MB,相比原始pt模型,推理速度提升30%以上。
3.3.2 INT8量化优化(关键)
为进一步降低模型体积、提升推理速度,对ONNX模型进行INT8量化(将FP32精度转为INT8,体积减小75%,速度提升2-4倍)。使用Rockchip官方的rknn-toolkit2工具(适配RK3588芯片)进行量化,步骤如下:
python
from rknn.api import RKNN
# 创建RKNN对象
rknn = RKNN()
# 配置量化参数(动态量化,无需校准数据集)
rknn.config(
quantize_method='dynamic', # 动态量化
target_platform='rk3588', # 目标芯片
mean_values=[[0, 0, 0]], # 均值(与训练时一致)
std_values=[[255, 255, 255]]# 标准差(与训练时一致)
)
# 加载ONNX模型
print("加载ONNX模型...")
ret = rknn.load_onnx(model='./best.onnx')
if ret != 0:
print("加载模型失败!")
exit(ret)
# 构建量化模型
print("构建量化模型...")
ret = rknn.build(do_quantization=True)
if ret != 0:
print("构建模型失败!")
exit(ret)
# 导出量化后的RKNN模型
ret = rknn.export_rknn('./best_quant.rknn')
if ret != 0:
print("导出模型失败!")
exit(ret)
# 释放资源
rknn.release()
print("INT8量化完成,生成best_quant.rknn")
量化完成后生成best_quant.rknn文件,体积仅2.1MB,可直接在香橙派上通过NPU加速推理。
四、香橙派端模型部署与实时推理

4.1 模型与代码传输到香橙派
使用scp命令将PC端的量化模型(best_quant.rknn)和推理代码传输到香橙派,PC端执行命令:
bash
# 传输量化模型
scp ./best_quant.rknn orangepi@192.168.1.105:/home/orangepi/screen_scratch_detect
# 传输推理代码(后续编写的infer.py)
scp ./infer.py orangepi@192.168.1.105:/home/orangepi/screen_scratch_detect
说明:192.168.1.105为香橙派的IP地址,/home/orangepi/screen_scratch_detect为香橙派上的目标目录(需提前创建)。
4.2 实时推理代码编写
在香橙派上创建infer.py文件,基于rknn-toolkit2加载量化模型,实现摄像头实时采集、模型推理、结果可视化,代码如下:
python
from rknn.api import RKNN
import cv2
import numpy as np
# 初始化RKNN模型
def init_rknn(model_path):
rknn = RKNN()
# 加载RKNN量化模型
ret = rknn.load_rknn(model_path)
if ret != 0:
print("加载RKNN模型失败!")
exit(ret)
# 初始化推理环境(指定RK3588芯片)
ret = rknn.init_runtime(target='rk3588', device_id='0')
if ret != 0:
print("初始化推理环境失败!")
exit(ret)
return rknn
# 图像预处理(适配模型输入要求)
def preprocess(img, input_size):
# 缩放图像
img_resize = cv2.resize(img, input_size)
# 归一化(与训练时一致)
img_norm = img_resize / 255.0
# 维度转换:HWC -> CHW
img_trans = np.transpose(img_norm, (2, 0, 1))
# 添加batch维度
img_input = np.expand_dims(img_trans, axis=0)
return img_input, img_resize
# 后处理(解析模型输出,得到检测框)
def postprocess(output, input_size, img_origin_shape, conf_thres=0.5):
# YOLOv8输出格式:[batch, num_boxes, 5+num_classes]
# 5代表x1,y1,x2,y2,conf,后续为类别概率
output = output[0]
# 筛选置信度>阈值的检测框
mask = output[:, 4] > conf_thres
boxes = output[mask, :4]
confs = output[mask, 4]
clses = np.argmax(output[mask, 5:], axis=1)
# 坐标转换:模型输入尺寸 -> 原始图像尺寸
h_origin, w_origin = img_origin_shape[:2]
h_input, w_input = input_size
scale_h = h_origin / h_input
scale_w = w_origin / w_input
boxes[:, 0] *= scale_w
boxes[:, 1] *= scale_h
boxes[:, 2] *= scale_w
boxes[:, 3] *= scale_h
return boxes.astype(np.int32), confs, clses
# 主推理函数
def main():
# 模型路径与参数
model_path = "./best_quant.rknn"
input_size = (640, 640)
class_names = ["scratch"] # 检测类别
# 初始化模型
rknn = init_rknn(model_path)
print("模型初始化完成,启动实时检测...")
# 打开摄像头(0为默认USB摄像头)
cap = cv2.VideoCapture(0)
# 设置摄像头分辨率(提升采集速度)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
if not cap.isOpened():
print("打开摄像头失败!")
return
while True:
# 读取一帧图像
ret, frame = cap.read()
if not ret:
print("读取图像失败!")
break
# 图像预处理
img_input, img_resize = preprocess(frame, input_size)
# 模型推理(NPU加速)
outputs = rknn.inference(inputs=[img_input])
# 后处理
boxes, confs, clses = postprocess(
outputs, input_size, frame.shape, conf_thres=0.5
)
# 绘制检测框与标签
for box, conf, cls in zip(boxes, confs, clses):
x1, y1, x2, y2 = box
# 绘制矩形框(绿色,线宽2)
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 绘制标签背景
label = f"{class_names[cls]}: {conf:.2f}"
cv2.rectangle(frame, (x1, y1-20), (x1+len(label)*12, y1), (0, 255, 0), -1)
# 绘制标签文本
cv2.putText(frame, label, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
# 显示推理结果
cv2.imshow("Screen Scratch Detection (Orange Pi)", frame)
# 按'q'退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
rknn.release()
if __name__ == "__main__":
main()
4.3 推理效果与性能测试
4.3.1 推理效果验证
在香橙派上运行推理代码:python3 infer.py,将摄像头对准待检测屏幕(如手机屏、车载屏),可实时看到屏幕划痕被绿色矩形框标注,标注框精准度高,即使是轻微划痕也能准确识别,无明显漏检、误检现象。
4.3.2 性能测试
在香橙派5(RK3588)上,基于量化后的RKNN模型测试性能,结果如下:
-
推理速度:单帧推理时间约18ms,帧率可达55FPS,远超目标的25FPS,满足实时质检需求;
-
资源占用:推理时CPU占用率约12%,内存占用约100MB,NPU占用率约35%,资源消耗低,可同时运行其他辅助程序(如数据上传、报警提示);
-
稳定性:连续运行2小时无崩溃,推理结果稳定,无漂移现象。
五、常见问题与解决方案
5.1 训练模型泛化能力差,对新场景划痕漏检
问题描述:模型在训练集上表现好,但在新的屏幕类型、新光照条件下漏检率高。
解决方案:1)扩充数据集,增加更多类型屏幕、不同光照(强光、暗光)、不同角度的划痕图像;2)增强数据增强强度,添加随机噪声、色域变换等;3)使用YOLOv8s模型重新训练(精度更高,泛化能力更强)。
5.2 香橙派端推理卡顿,帧率低
问题描述:推理帧率低于20FPS,无法满足实时需求。
解决方案:1)确保使用量化后的RKNN模型(而非原始pt模型或ONNX模型),充分利用NPU加速;2)降低摄像头采集分辨率(如从1920×1080降至1280×720);3)简化后处理代码,去除不必要的图像操作。
5.3 香橙派加载RKNN模型失败
问题描述:提示"Init runtime failed"或"Load rknn model failed"。
解决方案:1)检查rknn-toolkit2版本与香橙派芯片匹配(RK3588需用1.6及以上版本);2)重新执行模型量化,确保量化时target_platform设为"rk3588";3)重启香橙派,重新初始化NPU驱动。
六、总结与展望
6.1 项目总结
本项目基于YOLOv8实现了屏幕划痕的精准检测,并成功部署到香橙派边缘设备,核心优势的:1)轻量化:模型经量化后仅2.1MB,适配边缘设备资源限制;2)高精度:测试集mAP@0.5达92.3%,可识别微小划痕;3)高实时性:推理帧率55FPS,满足生产线高速质检需求;4)低成本:基于香橙派(约300元)构建边缘节点,大幅降低部署成本。
6.2 未来展望
后续可从以下方向优化方案:1)多缺陷检测:扩展数据集,增加屏幕污渍、破损、气泡等缺陷类型,实现多缺陷同时检测;2)远程监控:结合MQTT/HTTP协议,将检测结果(缺陷类型、位置、数量)上传到云端平台,实现远程监控与数据分析;3)自动报警:添加声音报警、灯光提示功能,当检测到缺陷时自动触发报警;4)模型迭代:使用YOLOv8m模型结合迁移学习,进一步提升复杂场景下的检测精度。
以上就是YOLOv8屏幕划痕检测与香橙派边缘推理的全流程分享,所有代码均经过实操验证,可直接复用。如果在实践过程中有任何问题,欢迎在评论区留言交流~