基于机器视觉的硬币分拣系统设计:从成像选型到OpenCV识别全解析

发布时间:2026/9/30 5:10:30
基于机器视觉的硬币分拣系统设计:从成像选型到OpenCV识别全解析 简介机器视觉技术将计算机视觉与机器人控制相结合在自动化检测与分拣领域具有典型应用价值。该PDF文档围绕基于机器视觉的硬币分拣系统设计展开面向自动化设备研发人员、高校机电或测控专业学生解决硬币识别、定位与抓取分拣中的算法及系统集成问题。文档内容涵盖图像预处理、特征约束、模板匹配等视觉算法以及相机坐标系与机械臂运动坐标系之间的转换方案并详细阐述了机械臂抓取完成自动分拣的完整流程。作为一篇技术论文文中还给出了实验验证结果表明系统在准确率与漏检率方面满足实际需求可为银行、商场等场景下的大批量硬币处理提供参考方案。资源为单个PDF文件压缩包大小约1.04MB属于技术文档类资料结构紧凑便于下载后直接阅读。目前已有266人学习浏览适合需要快速了解机器视觉分拣系统设计思路的读者。1. 一枚硬币从出现到入槽这个机器视觉分拣系统到底要解决什么收到硬币分拣系统的设计需求时很多人的第一反应是“用重量区分不就行了吗”但实际接触过项目就会明白重量传感器只能区分币种差异大的情况而且机械结构复杂、响应慢一旦遇到相同重量不同面值的硬币就彻底失灵。基于机器视觉的硬币分拣系统走的是另一条路——用相机拍下硬币的直径、形状、纹理和颜色在图像里算出特征再让执行机构把硬币推进对应的滑道。这个方法的最大价值是柔性换一套币种只需改软件里的特征库不用动机械。这套系统适合谁一是做课程设计或毕业设计的学生需要一份能跑通全流程的方案二是小型自动化设备厂商想给分拣机增加视觉识别能力三是在做硬币清分设备预研的工程师。整条技术链条并不复杂上料、成像、识别、分拣、统计每一环都有自己的坑。下面把各环节的选型逻辑、参数设置和踩坑经验一条条拆开讲目标是让读者照着这套思路能搭出一台样机而不是停留在PPT设计上。2. 先算视野和分辨率再选硬件成像系统的选型搭配2.1 视野和分辨率先定物理指标再碰相机硬币分拣系统的成像硬件由相机、镜头、光源和触发传感器构成。设计起点不是“买什么相机”而是“需要看清硬币的什么特征”。人民币硬币的直径在19mm到25mm之间如果要同时拍摄多枚硬币视野通常要覆盖整个分拣通道宽度会到40mm左右。判断一个硬币的面值最可靠的视觉特征是直径所以成像系统必须保证直径测量误差小于0.1mm。按视野40mm、最小精度0.1mm算横向像素至少需要400个。实际工程上不会卡着下限设计一般会把精度余量放到3到5倍也就是视野40mm时用1200到2000像素。这样算下来500万像素级别2448×2048的工业面阵相机是常见选择。如果只是单枚硬币逐个拍视野收窄到30mm200万像素也够用。镜头方面定焦C接口镜头焦距按工作距离反推焦距 工作距离 × 传感器靶面宽度 ÷ 视野宽度比如工作距离150mm、视野40mm、靶面宽度6.4mm1/1.8英寸焦距约为24mm。实际项目里因为支架尺寸限制常用8mm到16mm的短焦镜头配合更大工作距离关键是锁死后不要再动否则标定会失效。注意分辨率标称值不等于实测精度。要拿钢尺或标准量块放在视野里拍一张用像素数和实际尺寸反向算出每像素对应的毫米数这个数才是真正影响分拣准确率的标定系数。2.2 光源方案背光边缘优先前光做纹理辅助硬币识别的一个核心难题是表面反光。硬币是金属材质币面有浮雕图案如果只用前光环形光从上方打图像里会出现高光和阴影交错的现象二值化后硬币边缘变得参差不齐直径提取误差会被放大到肉眼可见的程度。我在实际方案里最常用的是背光照明把硬币放在透射光源上方相机从顶部拍。此时硬币在图像里呈现为黑色实心圆背景是亮的轮廓极其干净直接用大津法就能稳定分割。这种方案损失的是币面纹理信息但直径、形状因子这些最核心的特征已经足够完成人民币硬币的分拣。如果项目要求识别币面图案比如区分同直径同厚度的纪念币就在背光基础上增加一个低角度环形前光让币面字符和花纹进入图像用纹理特征做二次分类。两种光源不要同时全亮度工作否则图像容易出现过度曝光。照明时序上建议用控制器让光源只在相机曝光期间点亮这样既省电又减少发热对相机的影响。2.3 输送、触发和遮光三个容易被忽略的配套环节相机决定了成像质量的上限但输送机构才是决定系统能不能稳定运行的基础。常见的方案有两种振动盘加直振轨道适合单枚分离后逐个拍照和平带输送适合连续检测后分拣。振动盘方案的优势是硬币排列有序、间距可控但上料速度有限平带方案速度快但硬币姿态随机需要图像算法适应各种偏转角度和位置这给后续的轮廓提取增加了难度。对设计任务来说振动盘加直振轨道更容易把识别率做高建议优先考虑。触发传感器建议选对射式光电开关或金属接近开关。传感器信号触发相机采集避免让相机一直处于连续采集状态既节省算力又保证每一帧图像里都恰好只有一枚硬币。遮光罩也是必装的环境光变化会让图像的灰度分布整体漂移室内灯光、窗户透光、人员走动产生的阴影都会干扰阈值分割。用铝型材加遮光布做一个封闭小暗箱成本不到一百元能把环境光的干扰降到最低。3. 图像处理与特征提取从灰度图到面值判决的完整流程3.1 图像预处理滤波、二值化与形态学操作拿到相机原始图像后第一步不是直接找轮廓而是做预处理。常规流程是灰度化、滤波去噪、二值化、形态学处理。工业相机输出的是彩色图像或Bayer格式图像灰度化后用3×3或5×5的中值滤波去除传感器噪声。中值滤波对椒盐噪声效果好而且不会像高斯滤波那样把边缘磨糊是硬币图像的首选。二值化是整个流程里最影响成败的一步。固定阈值在环境光稳定的暗箱里可用但更推荐大津法Otsu它按图像的灰度分布自动算出阈值天然适应轻微的光照变化。OpenCV里的写法是import cv2 import numpy as np # 读取灰度图 img_gray cv2.imread(coin.jpg, cv2.IMREAD_GRAYSCALE) # 中值滤波去噪核大小取5 img_filtered cv2.medianBlur(img_gray, 5) # 大津法二值化自动求阈值高于阈值为255背景低于阈值为0硬币 _, img_binary cv2.threshold(img_filtered, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU) # 形态学开运算去除二值图里的小噪点 kernel np.ones((3, 3), np.uint8) img_morph cv2.morphologyEx(img_binary, cv2.MORPH_OPEN, kernel, iterations1)这段代码里用了THRESH_BINARY_INV cv2.THRESH_OTSU的组合目的是让背光下的硬币变成白色前景、黑色背景后续findContours找轮廓时逻辑更直观。MORPH_OPEN的作用是去掉硬币内部和边缘上的零星白点避免轮廓提取时出现毛刺。如果硬币表面有大面积高光反射残留下黑斑开运算核大小可以加到5×5但核太大会让边缘向内收缩影响直径测量精度这一点要特别注意。提示如果二值化后硬币内部出现黑色空洞由币面反光或污渍引起不要简单加大核。先用cv2.morphologyEx做闭运算把空洞补上再对轮廓做一次平滑处理效果比单纯调核参数好得多。3.2 轮廓提取与最小外接圆直径和形状因子的计算二值化之后就可以提取轮廓了。OpenCV 的findContours返回所有连通区域需要按面积过滤掉噪点和无关区域。硬币的面积在图像里是固定的几千到几万像素设一个面积上下限就能把干扰滤掉。然后对每个候选轮廓计算最小外接圆直径、轮廓面积、轮廓周长、圆形度形状因子这些特征就是后续分类的依据。# 提取轮廓只取最外层轮廓 contours, _ cv2.findContours(img_morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 面积阈值像素面积小于8000的多半是噪点超过20000的可能是粘连目标 valid_contours [] for cnt in contours: area cv2.contourArea(cnt) if 8000 area 20000: valid_contours.append(cnt) for cnt in valid_contours: # 最小外接圆得到圆心坐标和半径 (cx, cy), radius cv2.minEnclosingCircle(cnt) diameter_pixel radius * 2 # 轮廓周长与圆形度圆形度越接近1外形越接近标准圆 perimeter cv2.arcLength(cnt, True) circularity 4 * np.pi * area / (perimeter * perimeter) print(f直径(像素): {diameter_pixel:.2f}, 圆形度: {circularity:.4f})这段代码的关键逻辑有两个一是用面积先过滤掉明显不可能是硬币的连通域二是用minEnclosingCircle而非外接矩形求直径——因为硬币在传送带上会随机旋转外接矩形受姿态影响最小外接圆则对旋转不敏感。圆形度可以用来剔除折角、铁片等异形干扰物圆形度低于0.9的目标直接丢弃不再进入分类环节。3.3 特征数据库与分类判据直径为主灰度纹理为辅特征准备好以后下一步是建立分类标准。常见做法是把每种硬币的直径像素值、面积、圆形度、灰度均值写进一个特征表分类时逐一比对。以人民币硬币为例不同面值的直径差异明显1元硬币直径25mm5角硬币直径20.5mm1角硬币直径19mm。像素值需要乘以标定系数换算成毫米再与标准值比对。单纯靠直径其实已经能区分人民币的常见币种但同直径的版本差异比如不同年份的1元硬币就需要靠纹理特征辅助。# 标定系数相机标定时测得的每像素对应毫米数 pixel_to_mm 0.025 # 示例值实际需用标准量块标定 class CoinClassifier: def __init__(self): # 特征库直径(mm)下限、上限灰度均值范围 self.feature_db { 1元: {d_min: 24.5, d_max: 25.5, gray_min: 100, gray_max: 160}, 5角: {d_min: 20.0, d_max: 21.0, gray_min: 60, gray_max: 120}, 1角: {d_min: 18.5, d_max: 19.5, gray_min: 80, gray_max: 140}, } def classify(self, diameter_pixel, gray_mean): diameter_mm diameter_pixel * pixel_to_mm for coin_type, feature in self.feature_db.items(): if feature[d_min] diameter_mm feature[d_max]: if feature[gray_min] gray_mean feature[gray_max]: return coin_type return unknown分类逻辑采用的是区间匹配而不是最近邻匹配原因在于实际测量一定会存在误差硬币磨损、镜头畸变、光照波动都会让直径发生0.1到0.3mm的偏移。给每个币种留10%左右的阈值余量能明显降低误判率。灰度均值的引入是作为辅助判据区分直径接近但材质不同的硬币例如旧版1元硬币和新版1元硬币的灰度值有明显差异。3.4 实时性优化ROI裁剪和多线程采集识别速度直接影响分拣吞吐量。相机分辨率越高图像处理耗时越长。如果目标速度是每秒5枚硬币每帧图像的处理时间必须控制在200ms以内。优化手段有两个一是裁剪感兴趣区域通过光电触发信号估算硬币位置只处理硬币周围的局部图像二是把图像采集和处理放在两个线程采集线程持续写入缓存处理线程从缓存取帧进行识别。实测下来ROI裁剪能把处理时间缩短到原来的1/3左右效果立竿见影。另外需要注意的一点是相机曝光时间尽量调短。硬币在直振轨道上并非绝对静止曝光时间大于1ms时容易产生运动模糊导致轮廓边缘发虚。建议曝光时间设定在0.2ms到0.5ms之间配合背光光源的亮度补偿画面依然清晰。4. 分拣执行与联动控制视觉结果怎么变成推杆动作4.1 像素坐标与物理坐标的映射视觉识别输出的是硬币在图像里的位置和类别但执行机构需要的是“在哪个物理位置推动哪个滑道”。这中间需要做坐标映射。对固定安装的相机来说像素坐标到物理坐标的变换可以用最简单的等比例换算实现——前提是相机光轴垂直于传送面且没有透视畸变。安装相机时用水平尺校准让镜头平面与传送带平行这样标定只需要一个比例系数就够了。如果安装角度无法保证垂直就要用透视变换。常见做法是放一张棋盘格标定板提取角点后计算单应性矩阵OpenCV 的findHomography可以一行代码完成# 用四组对应点计算单应性矩阵 pts_src np.array([[x1, y1], [x2, y2], [x3, y3], [x4, y4]], dtypenp.float32) pts_dst np.array([[0, 0], [width, 0], [width, height], [0, height]], dtypenp.float32) homography_matrix, _ cv2.findHomography(pts_src, pts_dst) # 像素坐标映射到物理坐标 pixel_coord np.array([[[cx, cy]]], dtypenp.float32) physical_coord cv2.perspectiveTransform(pixel_coord, homography_matrix)这里pts_src是图像中棋盘格四个角点的像素坐标pts_dst是对应物理位置坐标。透视变换的好处是允许相机有一定的安装倾角不必苛求绝对垂直。但要注意一旦相机位置动了单应性矩阵就失效必须重新标定所以相机固定支架一定要用带锁紧的金属件不能靠摩擦力定位。4.2 PLC通讯与分拣时序提前量计算是核心识别到硬币类别之后需要把结果传给执行机构。常见执行方案有电磁推杆式、气动吹除式和翻板式。电磁推杆结构简单适合低速分拣气动吹除响应快适合高速场景翻板式适合硬币从轨道末端下落时改变轨迹。无论哪种方式PLC 都是控制核心。视觉系统通过串口RS232/RS485或以太网把分类结果发送给 PLCPLC 根据光电传感器的位置确定推杆动作时机。这里的核心参数是“提前量”也就是从拍照点到分拣点的距离除以传送带线速度。比如拍照点距离推杆200mm传送带速度200mm/s那么推杆动作信号必须在识别完成后的1秒触发。触发太早或太晚硬币都会错过推杆行程。一个更稳妥的做法是在每个分拣点前装一个光电传感器当硬币通过该传感器时PLC 立即查询最近一次视觉结果并决定是否动作这样就不依赖精确的速度计算了。# 简化版的串口输出逻辑识别到1元时发送字符 15角发送 2 import serial ser serial.Serial(/dev/ttyUSB0, 9600, timeout0.1) result classifier.classify(diameter_pixel, gray_mean) if result 1元: ser.write(b1) elif result 5角: ser.write(b2) else: ser.write(b0) # 未知类别默认不动作 ser.close()串口通讯是视觉系统与PLC之间最稳妥的方式。波特率9600虽然慢但一帧数据只有几个字节延迟可以忽略不计。要注意的是串口线缆必须用屏蔽双绞线并且与电机动力线分开走线否则变频器或步进驱动器启动时产生的电磁干扰会让通讯数据频繁出错——这是现场最隐蔽的坑之一。5. 硬币分拣常见问题排查5个翻车现场与整改措施5.1 币面反光导致二值化后出现“黑洞”现象背光照明下硬币内部出现不规则黑色区域轮廓提取后硬币边缘呈锯齿状直径计算忽大忽小。原因硬币表面并非完全均匀。币面浮雕图案在透射光下仍会形成局部高光或阴影导致二值化后内部产生空洞此外如果硬币有污渍或氧化层也会让局部灰度低于阈值。解决先做形态学闭运算填补内部空洞再做轮廓提取。闭运算的核大小从3×3试到7×7以硬币边缘不产生明显膨胀为准。如果空洞仍严重调整背光亮度让硬币整体亮度落在阈值曲线的中间区域而不是接近边界。5.2 硬币粘连导致轮廓错分现象两枚硬币在轨道上挨得很近二值化后变成一个连通域面积翻倍无法正确识别任何一枚。原因振动盘送料节奏不稳定或者直振轨道上硬币间距过小。面积筛选无法区分两个粘连硬币与一个大面积异物。如果强行按面积上限截断则粘连硬币的直径特征也会被污染。解决优先在机械上拉开间距振动盘的频率和直振轨道的振幅是主要调节手段。图像侧可以加一层保护检测到连通域面积超过单枚硬币面积上限的1.5倍就判定为“多枚粘连”直接发送剔除信号不进入分类。这样可以避免把粘连目标误判成某种币。5.3 运动模糊硬币边缘不是圆而是椭圆现象图像中硬币边缘沿运动方向拖尾测量出的直径在运动方向上偏大。原因硬币在轨道上存在滑动或微小跳动曝光时间内目标位移超过一个像素。虽然直振轨道的振动幅度很小但在曝光时间偏长时依然会产生明显影响。解决把相机曝光时间从1ms往下调配合更高亮度的背光源来补偿进光量。经验值是把曝光时间控制在0.3ms以内光源亮度调到相机灰度直方图最高峰在180到220之间。如果硬币确实存在跳动还需要检查轨道是否有台阶或磨损点机械问题靠图像处理是救不了的。5.4 环境光导致阈值漂移现象白天的识别率正常到了傍晚识别率下降固定阈值方案尤其明显。原因遮光罩没有完全密封视觉系统安装在窗边或靠近门口环境光照强度随天气和时间变化。解决两个手段并用。算法上用大津法替代固定阈值让阈值自动适应灰度分布硬件上把遮光罩的接缝用黑色遮光布或密封条堵死相机镜头前加装偏振片进一步减少杂散光。这套组合能解决绝大部分环境光干扰。5.5 标定失效识别率突然集体下降现象系统运行一段时间后所有硬币的直径测量值整体偏移0.5mm以上分类大面积出错。原因相机支架松动、镜头调焦环转动、传送带更换造成拍照距离变化都会让像素当量失效。还有一种隐蔽原因相机重启后自动增益功能开启导致图像整体变亮或变暗灰度特征发生漂移。解决每次开机后自动执行一次标定验证在轨道上放一枚已知直径的标准硬币测量直径偏差是否在允许范围内。超出允许范围就停机报警。给相机的手动/自动增益模式锁死为手动曝光时间、增益、白平衡参数全部固定写入配置文件不许运行时自动调整。6. 让系统真正可交付验证指标与上线前的小技巧样机跑通不等于系统稳定交付前需要一套客观的验证方法。先采集每种硬币各100枚以上建立标准样本库记录每枚硬币的直径、面积、圆形度、灰度均值算出均值和标准差。然后用这份样本库的统计量生成分类阈值而不是凭经验拍脑袋。分类效果的衡量指标用精确率和召回率精确率是分拣结果中正确的比例召回率是所有该分拣出的硬币中被正确分拣出来的比例。对分拣系统来说召回率比精确率更重要——漏掉一枚1元硬币的代价比误判一枚5角硬币更大所以分类阈值可以设计得偏向“不确定就剔除”由人工复检。调试顺序上也有一个实用技巧先关闭剔除机构让系统只做识别和统计观察连续100枚硬币的分类准确率。识别率达标后再打开剔除机构此时错误集中在机械位置偏差而不在视觉算法排查范围立刻缩小一半。这个习惯能省下大量现场调试时间。最后我自己的习惯是准备一个配置文件位置、曝光、阈值、特征库全部外置不写死在代码里。每次换币种、换镜头、换轨道只改配置不碰程序系统维护的人从我自己变成任何会写配置文件的人。这个习惯不一定漂亮但让项目交付后的支持成本低了不少。希望帮到你。本文还有配套的精品资源点击获取