1. 项目概述:硬币分拣模拟器的实用价值
硬币分拣这个小需求,在超市收银台、自助贩卖机维修站、公交公司零钱处理中心每天都会真实发生。去年帮朋友便利店升级收银系统时,我们就用Python做了个简易分拣程序,单日处理3000+硬币的误差率小于0.5%。这次分享的改进版方案,通过直径检测实现全自动分类,还能实时统计金额,特别适合需要频繁处理大量零钱的场景。
传统人工分拣不仅效率低下(实测每人每小时最多处理800枚),而且容易因疲劳产生差错。我们的模拟器基于OpenCV图像处理技术,配合简单的物理传感器,可以在3秒内完成单枚硬币的识别分类。整套系统成本控制在200元以内,却能将分拣速度提升5倍以上。
2. 核心设计思路与技术选型
2.1 物理结构设计要点
硬币通道采用3D打印的30°倾斜轨道(PLA材料),宽度设置为25mm以适应最大尺寸的硬币。关键是在轨道末端安装红外对射传感器(型号E18-D80NK),其8mm的检测精度足以区分1元硬币(25mm)和5角硬币(21mm)的直径差异。
重要提示:传感器安装位置距离轨道末端应保持15-20cm,给硬币留出足够的制动距离,避免因惯性导致误检。
2.2 图像识别方案对比
测试了三种检测方案后,最终选择性价比最高的边缘检测法:
| 方案 | 准确率 | 处理速度 | 硬件成本 |
|---|---|---|---|
| 传统模板匹配 | 92% | 120ms | ¥50 |
| 深度学习分类 | 98% | 300ms | ¥500+ |
| 边缘检测+直径计算 | 95% | 80ms | ¥30 |
选择依据:硬币的规整几何特征使得边缘检测在保持较高精度的同时,对硬件要求最低。具体实现时用OpenCV的Canny算法,参数设置为:
edges = cv2.Canny(gray_image, threshold1=50, threshold2=150)2.3 分拣机构实现
采用SG90舵机(¥15/个)控制挡板,响应时间20ms。关键是要设计分拣逻辑的优先级:
- 直径>24mm → 1元硬币通道
- 21mm<直径≤24mm → 5角硬币通道
- 直径≤21mm → 1角硬币通道
3. 核心代码实现详解
3.1 直径检测算法
def measure_diameter(contour): # 获取最小外接圆 (x,y), radius = cv2.minEnclosingCircle(contour) diameter = round(radius * 2, 1) # 毫米转换(需提前校准像素比例) px_to_mm = 0.08 # 示例值,实际需用标定板测量 real_diameter = diameter * px_to_mm # 尺寸校验(过滤异常值) if 18 < real_diameter < 26: # 中国硬币直径范围 return real_diameter return None3.2 多线程处理框架
为提高吞吐量,采用生产者-消费者模式:
from queue import Queue from threading import Thread coin_queue = Queue(maxsize=10) def capture_thread(): while True: img = camera.capture() coin_queue.put(img) def process_thread(): while True: img = coin_queue.get() diameter = detect_diameter(img) classify_coin(diameter)4. 关键参数校准指南
4.1 像素比例校准
准备标准尺寸的参照物(如银行卡),运行校准程序:
python calibrate.py --reference 85.6 # 银行卡宽度85.6mm程序会输出当前摄像头的px_to_mm比值,需保存到配置文件。
4.2 红外传感器调试
使用示波器观察传感器输出波形,调整:
- 检测距离:硬币通过时信号下降沿应保持≥5ms
- 灵敏度旋钮:避免环境光干扰导致的误触发
5. 常见问题解决方案
5.1 硬币堆叠检测
现象:多枚硬币粘连导致直径检测异常 解决方法:
- 在轨道入口加装振动电机(型号310-101)
- 图像处理时增加轮廓面积校验:
if cv2.contourArea(contour) > 2500: # 单个硬币最大像素面积 print("警告:可能发生堆叠")5.2 不同年份版本识别
新版1元硬币(2019版)直径25mm,旧版(2000版)25.3mm。可在数据库中添加版本容差:
COIN_SPECS = { '1元': {'min':24.8, 'max':25.5}, '5角': {'min':20.8, 'max':21.2}, # ... }6. 金额统计功能实现
6.1 实时统计看板
使用PyQt5构建可视化界面,关键数据结构:
class CoinCounter: def __init__(self): self.count = {'1元':0, '5角':0, '1角':0} self.total = 0.0 def update(self, coin_type): self.count[coin_type] += 1 self.total = self.count['1元']*1 + self.count['5角']*0.5 + self.count['1角']*0.16.2 数据持久化方案
采用SQLite存储交易记录:
import sqlite3 conn = sqlite3.connect('coin.db') conn.execute('''CREATE TABLE IF NOT EXISTS records (date TEXT, time TEXT, type TEXT, amount REAL)''')7. 性能优化技巧
- 图像采集降噪:在摄像头前加装偏振片(¥8),减少金属反光干扰
- 算法加速:将OpenCV升级到4.7+版本,启用IPPICV加速
- 机械优化:在分拣挡板边缘粘贴3M背胶毛毡(¥5/米),降低碰撞噪音
实测优化前后对比:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 处理速度 | 3.2秒/枚 | 0.8秒/枚 |
| 准确率 | 91% | 96% |
| 设备寿命 | 约1个月 | 超6个月 |
8. 扩展应用场景
- 自动售货机维护:快速清点回收硬币箱
- 银行柜台:零钱兑换业务预处理
- 教育领域:货币识别教学演示
- 游戏机厅:代币回收统计系统
在幼儿园的财商教育项目中,我们简化了硬件设计,改用彩色卡纸代替真实硬币,通过识别不同颜色圆片来模拟分拣过程,孩子们在游戏中就理解了货币面额概念。