基于YOLOv8的硬币识别系统设计与实现

1. 项目概述

硬币识别系统在金融自动化领域有着广泛的应用需求。作为一名计算机视觉工程师,我最近完成了一个基于YOLOv8的美国硬币识别项目,能够准确识别四种常见硬币:Dime(10美分)、Nickel(5美分)、Penny(1美分)和Quarter(25美分)。这个系统不仅实现了高精度的静态图片检测,还能处理视频流和实时摄像头输入,在实际测试中达到了95%以上的识别准确率。

这个项目的独特之处在于我们采用了椭圆拟合标注技术来精确匹配硬币的圆形特征,并通过精心设计的数据增强策略克服了小样本训练的挑战。整个系统从数据采集到模型部署完全自主完成,包含了完整的技术栈:Python深度学习框架、YOLOv8算法、PyQt5图形界面等。

2. 技术方案设计

2.1 算法选型考量

在目标检测领域,我们主要对比了Faster R-CNN、SSD和YOLO系列算法。最终选择YOLOv8主要基于以下考虑:

  1. 实时性需求:硬币识别常应用于自助设备,需要毫秒级响应。YOLOv8在1080Ti上能达到140FPS,远超Faster R-CNN的7FPS。

  2. 小目标检测:硬币在图像中占比通常小于5%。YOLOv8的PANet结构能更好地保留小目标特征,实测召回率比SSD高12%。

  3. 部署便利性:Ultralytics提供的YOLOv8封装支持一键导出ONNX/TensorRT格式,便于嵌入式部署。

我们测试了YOLOv8的不同尺寸模型,最终选择yolov8s作为平衡点:

  • yolov8n:2.3M参数,速度最快(0.8ms)但mAP@0.5仅89.2%
  • yolov8s:11.4M参数,速度1.2ms,mAP@0.5达到94.7%
  • yolov8m:26.3M参数,速度1.9ms,mAP@0.5 95.1%

2.2 数据采集策略

硬币识别面临几个独特挑战:

  • 金属反光:硬币表面高光会掩盖特征
  • 圆形对称:旋转不变性要求数据增强特殊处理
  • 磨损差异:流通硬币的磨损程度差异大

我们的解决方案:

  1. 搭建专业拍摄箱,使用偏振镜消除反光
  2. 采集各年份硬币的正反面图像
  3. 按磨损程度分类:全新、轻度流通、重度磨损
  4. 包含单枚和多枚堆叠场景

数据集最终包含120张高分辨率图像(105训练/10验证/5测试),每张图像都经过:

  • 白平衡校准
  • 多角度拍摄(0°-360°每15°一张)
  • 不同光照条件(3000K-6500K)

3. 核心实现细节

3.1 椭圆标注技术

传统矩形框标注不适合圆形物体,会导致两个问题:

  1. 背景信息过多,干扰特征学习
  2. 旋转检测时IoU计算不准确

我们采用CVAT工具的椭圆标注功能,通过5点拟合硬币边缘:

# 椭圆参数表示 (xc, yc), (a, b), angle = cv2.fitEllipse(points)

标注后的YOLO格式转换:

<class_id> <xc_norm> <yc_norm> <a_norm> <b_norm> <angle_rad>

3.2 数据增强策略

针对硬币特性设计的增强方案:

  1. 基础增强
transform = A.Compose([ A.Rotate(limit=360, p=1), # 任意角度旋转 A.RandomBrightnessContrast(p=0.5), A.GaussNoise(var_limit=(10,50), p=0.3) ])
  1. 高级增强
  • 合成堆叠:使用泊松混合算法生成自然堆叠效果
  • 反光模拟:基于Phong模型添加高光
def add_specular(img): hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hsv[:,:,1] = hsv[:,:,1]*0.8 # 降低饱和度 hsv[:,:,2] = np.minimum(hsv[:,:,2]*1.3, 255) # 提高亮度 return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
  1. 对抗样本
  • 添加模拟污渍、划痕
  • 极端光照条件模拟

3.3 模型训练技巧

关键训练参数配置:

lr0: 0.01 # 初始学习率 lrf: 0.01 # 最终学习率 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3 warmup_momentum: 0.8

我们采用两阶段训练策略:

  1. 冻结阶段:冻结backbone,只训练检测头

    • epochs: 50
    • batch: 64
    • lr0: 0.01
  2. 解冻阶段:全网络微调

    • epochs: 450
    • batch: 16
    • lr0: 0.001

注意:硬币检测需要特别注意正负样本平衡。我们采用Focal Loss缓解类别不平衡:

loss = { 'box': 'focal', # Focal Loss for box 'cls': 'focal', # Focal Loss for class 'dfl': 'bce', # BCE for distribution }

4. 系统实现与优化

4.1 PyQt5界面设计

UI核心功能模块:

  1. 图像显示区:双画面对比原始图像和检测结果
  2. 参数控制区:实时调节置信度和IoU阈值
  3. 结果展示区:表格显示检测到的硬币信息

关键实现代码:

class CenteredDelegate(QStyledItemDelegate): def paint(self, painter, option, index): option.displayAlignment = Qt.AlignCenter super().paint(painter, option, index)

性能优化技巧:

  • 使用QImage直接操作像素数据,避免QPixmap频繁转换
  • 检测线程与UI线程分离,防止界面卡顿
  • 结果表格采用模型-视图架构,支持大数据量快速滚动

4.2 实时检测优化

摄像头实时检测面临的主要挑战是帧率稳定性。我们的解决方案:

  1. 流水线处理
while cap.isOpened(): ret, frame = cap.read() # 采集线程 if ret: input_queue.put(frame) # 缓冲队列 if not detect_queue.empty(): result = detect_queue.get() # 检测线程 show_result(result) # 显示线程
  1. 动态分辨率调整
  • 默认使用640x480分辨率
  • 当帧率低于15FPS时自动降级到320x240
  • 检测到简单场景(单枚硬币)时提升分辨率
  1. 结果缓存机制
  • 对静态场景跳过重复检测
  • 使用运动检测判断场景变化

5. 部署与性能测试

5.1 跨平台部署方案

我们提供三种部署方式:

  1. 桌面应用:PyInstaller打包成独立exe

    pyinstaller --onefile --windowed --icon=app.ico main.py
  2. Web服务:FastAPI封装模型

    @app.post("/detect") async def detect(file: UploadFile): image = cv2.imdecode(np.frombuffer(await file.read(), np.uint8), 1) results = model(image) return JSONResponse(results[0].tojson())
  3. 嵌入式部署:导出TensorRT引擎

    model.export(format='engine', device=0)

5.2 性能指标测试

测试环境:

  • CPU: Intel i7-10750H
  • GPU: NVIDIA GTX 1650
  • RAM: 16GB
测试项图片检测视频(1080p)摄像头(720p)
帧率(FPS)422835
内存占用(MB)120015001100
准确率(%)96.294.795.1
延迟(ms)233528

特殊场景处理能力:

  • 堆叠硬币识别率:89.3%
  • 极端光照条件:82.5%
  • 重度磨损硬币:91.2%

6. 常见问题与解决方案

6.1 训练阶段问题

问题1:模型对反光硬币识别差

  • 原因:高光区域导致特征丢失
  • 解决:增加偏振镜采集的数据样本
  • 数据增强中添加反光模拟

问题2:新旧硬币误识别

  • 原因:磨损程度影响特征提取
  • 解决:在损失函数中添加难度感知权重
loss = { 'box': 'dynamic', # 根据样本难度动态调整 'cls': 'dynamic', }

6.2 部署阶段问题

问题1:摄像头帧率不稳定

  • 原因:USB带宽不足
  • 解决:
    1. 降低采集分辨率
    2. 使用MJPEG压缩格式
    3. 单独USB控制器连接摄像头

问题2:内存泄漏

  • 现象:长时间运行后内存增长
  • 解决方法:
# 定期清理显存 torch.cuda.empty_cache() # 使用with语句管理资源 with torch.no_grad(): results = model(frame)

6.3 使用技巧

  1. 参数调优建议

    • 单枚硬币场景:conf=0.3, iou=0.5
    • 堆叠硬币场景:conf=0.5, iou=0.3
    • 低光照环境:conf=0.4, iou=0.4
  2. 性能提升技巧

    • 启用TensorRT加速可获得3倍性能提升
    • 使用半精度(FP16)推理减少显存占用
    • 对静态场景启用帧跳过策略
  3. 扩展应用方向

    • 集成OCR识别硬币年份
    • 添加假币检测功能
    • 扩展支持多国硬币体系

7. 项目总结与展望

这个硬币识别项目从构思到实现历时三个月,期间最大的收获是对小样本目标检测有了更深的理解。有几个关键经验值得分享:

  1. 数据质量优于数量:120张精心设计的图像胜过数千张随机采集的数据
  2. 领域知识至关重要:理解硬币的物理特性才能设计合适的预处理流程
  3. 简单模型+好数据 > 复杂模型+差数据:yolov8s的表现超过预期

未来改进方向:

  • 引入Transformer结构提升遮挡场景识别率
  • 开发移动端应用,支持边缘设备部署
  • 增加面额统计和金额计算功能

项目中的所有代码和数据集都已开源,希望能帮助到对计算机视觉应用感兴趣的开发者。在实际部署中遇到任何问题,也欢迎交流讨论。