ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VisionPro入门实战:零件测量、硬币统计与骰子点数三大案例详解

VisionPro入门实战:零件测量、硬币统计与骰子点数三大案例详解 简介这份资源是面向机器视觉初学者与工业检测开发者的VisionPro案例合集围绕尺寸测量、目标计数与瑕疵检测等典型任务帮助读者理解视觉软件在自动化产线与质量控制中的落地方式。包内包含零件尺寸测量与显示、硬币统计、骰子点数统计、零件孔位数量统计、零件瑕疵检测、啤酒盖瑕疵检测、书签类型检测、手机电池正反面识别、车牌识别、陶瓷釉面瑕疵检测标注、地面裂痕检测标注、杂志页排序、药物胶囊瑕疵检测等十余个场景覆盖定位、测量、识别与缺陷标注等常见需求。资源共930个文件以jpg与bmp图像样本、cs与resx工程代码、vpp视觉程序、png与tif素材为主另有csproj、sln、dll、exe等工程与运行文件压缩包约65.75MB目录按案例组织便于对照图像与程序逐项复现。目前已有127人学习适合希望借助现成案例快速上手VisionPro、积累检测方案与排错思路的读者参考。1. 从一枚硬币到一颗骰子VisionPro 案例里藏着机器视觉的入门捷径很多人第一次接触康耐视 VisionPro都是从「零件尺寸测量与显示、硬币统计、骰子点数统计」这三个经典案例开始的。它们看起来像玩具题实际上把工业视觉最核心的三件事——定位、测量、计数分类——全串了一遍。硬币统计练的是 Blob 分析和圆拟合骰子点数练的是斑点分割与阈值鲁棒性零件尺寸测量练的是卡尺、找边和坐标系标定。这三个案例跑通你基本就摸到了 VisionPro 二次开发和联合 C# 硬触发的门槛。这篇文章不聊虚的直接按「原理讲清 → 步骤可抄 → 参数可调 → 坑点可查」的节奏把这三个案例从建工具到出结果的完整路径拆开。适合刚上手 VisionPro 的工程师也适合想把这几个案例改造成产线检测方案的熟手。2. 零件尺寸测量与显示从标定到卡尺的完整链路零件尺寸测量是 VisionPro 里最像「正经工业活」的部分。它不像硬币统计那样靠面积就能糊弄过去尺寸测量要求你先把像素坐标转换成物理毫米再用卡尺工具去抓边最后把结果稳定地显示出来。这一章把这条链路拆成可复现的步骤。2.1 为什么必须先做标定再谈测量VisionPro 里所有测量工具输出的都是像素值直接拿像素数当毫米用换个镜头或调个焦距就全废了。标定的本质是求一个比例系数一个像素对应多少毫米。常见做法是用一块已知尺寸的标定板或者干脆用一枚已知直径的标准件。在 VisionPro 里标定通过 CogCalibCheckerboardTool 或 CogCalibNPointToNPointTool 完成。棋盘格标定适合有畸变的镜头N 点标定适合视野平整、只需要比例换算的场景。对于零件尺寸测量这种平面测量任务N 点标定通常够用操作也更简单。标定完成后VisionPro 会生成一个 Calibration 对象后续所有测量工具引用它输出的就是物理单位。这一步没做后面所有尺寸都是「像素数」显示出来也没意义。2.2 用 CogFindLineTool 抓边并输出尺寸零件尺寸测量的核心是找边。VisionPro 提供 CogFindLineTool 和 CogCaliperTool前者找直线边缘后者找一对边缘并直接给出距离。对于规则零件我一般用 CogCaliperTool 直接测宽度或高度因为它一步就能输出「边到边」的距离。下面是一段用 C# 调用 CogCaliperTool 的典型代码假设已经加载了图像并完成了标定// 创建卡尺工具 CogCaliperTool caliper new CogCaliperTool(); // 设置搜索区域沿 X 方向搜索起点和终点定义搜索带 caliper.Region new CogRectangleAffine(); caliper.Region.SetCenterLengthsRotationSkew( centerX, centerY, // 搜索带中心 searchLength, // 搜索带长度 searchWidth, // 搜索带宽度 0, // 旋转角0 表示水平搜索 0); // 关键参数边缘极性、对比度阈值、滤波 caliper.EdgeMode CogCaliperEdgeModeConstants.SingleEdge; caliper.Edge0Polarity CogCaliperPolarityConstants.DarkToLight; caliper.ContrastThreshold 15; // 对比度阈值太低会抓到噪声 caliper.FilterHalfSize 2; // 滤波半宽抑制毛刺 // 执行 caliper.InputImage cogImage; caliper.Run(); // 读取结果位置是像素经过标定后才是毫米 double pixelPos caliper.Results[0].PositionX; double mmPos pixelPos * calibrationScale; // calibrationScale 来自标定这段代码里ContrastThreshold和FilterHalfSize是最需要调的。对比度阈值设太低边缘会跳到零件表面的纹理上设太高弱边缘直接找不到。滤波半宽增大能平滑毛刺但会让边缘位置略微偏移精密测量时要在「稳」和「准」之间取舍。2.3 把测量结果稳定显示到界面测量出来只是第一步显示不稳等于白测。VisionPro 的显示通常通过 CogRecordDisplay 控件完成把工具结果图形叠加到图像上。常见做法是给每个测量项建一个 CogGraphicLabel把毫米值写上去。// 在显示控件上叠加测量结果 CogGraphicLabel label new CogGraphicLabel(); label.SetXYText(resultX, resultY, $宽度: {widthMm:F3} mm); label.Color CogColorConstants.Green; label.Font new Font(Arial, 12); cogRecordDisplay1.InteractiveGraphics.Add(label, measure, false); cogRecordDisplay1.Fit();显示这块最容易翻车的是刷新时机。如果在工具还没跑完就刷新会显示上一次的结果操作员看到的就是「滞后一帧」的数据。正确做法是在Run()完成并确认Results有效后再更新图形。另外Fit()会改变缩放如果产线上要求固定视野就别每次调用它。提示测量结果显示建议保留三位小数但内部计算不要提前四舍五入否则累积误差会在多工位测量时暴露出来。3. 硬币统计Blob 分析加圆拟合的实战参数硬币统计看起来简单但它是理解 VisionPro Blob 分析的最佳入口。硬币有固定形状、明显边缘、和背景对比度高正好用来练分割和计数。这一章把从阈值分割到圆拟合的每一步参数讲透。3.1 Blob 分析的分割逻辑与阈值选择Blob 分析的第一步是把硬币从背景里分出来。VisionPro 用 CogBlobTool 做这件事核心是阈值。阈值分固定阈值和自适应阈值硬币统计一般用固定阈值就够因为硬币和背景的灰度差通常很大。CogBlobTool blob new CogBlobTool(); blob.InputImage cogImage; // 阈值模式固定阈值范围 0-255 blob.Mode CogBlobModeConstants.HardFixedThreshold; blob.Threshold new CogBlobThreshold(); blob.Threshold.Mode CogBlobThresholdModeConstants.HardFixedThreshold; blob.Threshold.LowValue 80; // 低于 80 的算背景 blob.Threshold.HighValue 255; // 高于 255 不存在实际就是 80 以上算硬币 // 面积过滤去掉太小和太大的区域 blob.Area new CogBlobArea(); blob.Area.Mode CogBlobAreaModeConstants.Area; blob.Area.LowValue 500; // 小于 500 像素的不要 blob.Area.HighValue 50000; // 大于 50000 像素的不要 blob.Run(); int coinCount blob.Results.GetBlobs().Count;LowValue设 80 是个经验值实际要看你的打光。背光照明下硬币是黑的阈值逻辑要反过来。面积过滤是防误检的关键灰尘、反光点、图像边缘的碎片都会被面积下限挡掉。上限则防止把整个托盘当成一个硬币。3.2 圆拟合与重叠硬币的处理硬币挨在一起时Blob 会把它们连成一片计数就少了。这时候要用圆拟合。VisionPro 的 CogFindCircleTool 可以在 Blob 区域内找圆或者用 CogBlobTool 的「分水岭」分割模式把粘连区域切开。// 对每个 Blob 区域尝试圆拟合 foreach (CogBlobResult blobResult in blob.Results.GetBlobs()) { CogFindCircleTool circleTool new CogFindCircleTool(); circleTool.InputImage cogImage; circleTool.Region blobResult.GetRegion(); // 用 Blob 区域限定搜索范围 // 圆拟合参数 circleTool.CircleRadius new CogFindCircleRadius(); circleTool.CircleRadius.LowValue 20; // 最小半径 circleTool.CircleRadius.HighValue 60; // 最大半径 circleTool.EdgeThreshold 10; circleTool.Run(); if (circleTool.Results.Count 0) { // 拟合成功确认是一枚硬币 validCoins; } }半径范围要根据实际硬币在图像里的像素尺寸来设。设太宽会把不是圆的东西也拟合进去设太窄稍微有点遮挡的硬币就漏掉。边缘阈值和卡尺工具类似太低会抓到硬币表面的花纹。重叠硬币的另一个思路是用「距离变换 分水岭」VisionPro 的 Blob 工具里有对应的分割选项但参数比较玄学需要根据硬币间距反复试。我一般先用圆拟合拟合不出来的再考虑分水岭。3.3 计数结果的去重与输出圆拟合有个坑同一个硬币可能被拟合出多个圆或者一个圆跨了两个硬币。去重的逻辑是检查圆心距离如果两个圆心距离小于半径就认为是同一个。ListCogCircle finalCircles new ListCogCircle(); foreach (var circle in allCircles) { bool isDuplicate false; foreach (var existing in finalCircles) { double dist Math.Sqrt( Math.Pow(circle.CenterX - existing.CenterX, 2) Math.Pow(circle.CenterY - existing.CenterY, 2)); if (dist circle.Radius * 0.8) // 圆心太近判为重复 { isDuplicate true; break; } } if (!isDuplicate) finalCircles.Add(circle); } int finalCount finalCircles.Count;0.8这个系数是经验值硬币排列紧密时可以调到 0.6稀疏时可以放到 1.0。去重之后再把最终数量显示到界面和零件测量一样用 CogGraphicLabel 叠加。注意硬币统计的稳定性高度依赖打光。环形光下硬币边缘清晰同轴光下反而可能因为反光导致边缘断裂。如果计数结果跳动先查光源再查参数。4. 骰子点数统计阈值分割与斑点识别的细节骰子点数统计比硬币统计难一层因为骰子上的点斑点是小目标而且点数会变。这个案例练的是小目标分割和分类计数。核心思路是先找到骰子区域再在区域内分割斑点最后按斑点数量判断点数。4.1 骰子区域定位与 ROI 提取骰子在图像里可能位置不固定所以第一步是定位。如果骰子颜色和背景差异大用 Blob 找最大区域即可如果背景复杂用 CogPMAlignTool 做模板匹配更稳。// 用模板匹配定位骰子 CogPMAlignTool pmAlign new CogPMAlignTool(); pmAlign.InputImage cogImage; pmAlign.Pattern.TrainImage templateImage; // 预先训练的骰子模板 pmAlign.Pattern.Origin new CogPointMarker(); // 模板原点 // 匹配参数 pmAlign.RunParams.AcceptThreshold 0.7; // 接受阈值低于 0.7 不算匹配 pmAlign.RunParams.ZoneScale 1.0; // 尺度搜索范围 pmAlign.RunParams.ZoneAngle new CogFindLineAngle(); // 角度搜索范围 pmAlign.Run(); if (pmAlign.Results.Count 0) { // 提取骰子区域作为后续处理的 ROI CogRectangleAffine diceRegion pmAlign.Results[0].GetPose(); // 后续斑点分析在这个区域内进行 }AcceptThreshold设 0.7 是平衡漏检和误检的常用值。骰子如果会旋转ZoneAngle要设成 ±180 度如果只是平移设 0 能加快速度。模板训练时尽量用对比度高的图像骰子上的点要清晰可见。4.2 斑点分割阈值、面积和形态学处理拿到骰子区域后用 Blob 工具分割斑点。斑点是暗的骰子面是亮的所以阈值逻辑是「暗于某个值算斑点」。CogBlobTool spotBlob new CogBlobTool(); spotBlob.InputImage cogImage; spotBlob.Region diceRegion; // 限定在骰子区域内 // 阈值暗斑点 spotBlob.Threshold.Mode CogBlobThresholdModeConstants.HardFixedThreshold; spotBlob.Threshold.LowValue 0; spotBlob.Threshold.HighValue 60; // 灰度低于 60 算斑点 // 面积过滤斑点有大有小但不会太小 spotBlob.Area.Mode CogBlobAreaModeConstants.Area; spotBlob.Area.LowValue 30; // 去掉噪声点 spotBlob.Area.HighValue 2000; // 去掉整块阴影 // 形态学开运算去掉毛刺 spotBlob.Morphology.Mode CogMorphologyModeConstants.Open; spotBlob.Morphology.KernelSize 3; spotBlob.Run(); int spotCount spotBlob.Results.GetBlobs().Count;HighValue设 60 取决于打光。如果骰子面有反光斑点灰度可能偏高这时候要么调光源要么把阈值往上提。面积下限 30 是滤掉噪声上限 2000 是防止把骰子边缘的阴影当成一个大斑点。形态学开运算的核大小 3 是保守值斑点本身很小的时候不要用太大的核否则斑点会被腐蚀掉。4.3 点数判定与结果输出斑点数量出来了但骰子点数不是简单等于斑点数量——因为骰子有 1 到 6 点而斑点数量就是点数。所以spotCount直接就是点数。但要注意如果骰子面有污渍可能多出假斑点如果斑点粘连可能少算。// 点数判定斑点数量即点数但要做合理性检查 int diceValue spotCount; // 合理性检查骰子点数只能是 1-6 if (diceValue 1 || diceValue 6) { // 异常可能是分割出错标记为无效 diceValue -1; } // 显示结果 CogGraphicLabel diceLabel new CogGraphicLabel(); diceLabel.SetXYText(diceCenterX, diceCenterY, $点数: {diceValue}); diceLabel.Color diceValue 0 ? CogColorConstants.Green : CogColorConstants.Red; cogRecordDisplay1.InteractiveGraphics.Add(diceLabel, dice, false);合理性检查很重要。如果分割参数没调好斑点数量可能是 0 或 7、8这时候直接显示会误导操作员。标记为红色或无效让操作员知道这一帧不可信。提示骰子点数统计的难点不在算法在打光的一致性。同一批骰子如果材质不同反光差异会让阈值失效。产线上建议固定光源角度和强度不要靠调阈值去适应每一颗骰子。5. 避坑与排查VisionPro 这三个案例最容易翻车的地方这三个案例我反复做过很多遍每次翻车的原因都差不多。这一章把最常见的五个坑列出来按「现象 → 原因 → 解决」写方便你对照排查。5.1 标定后尺寸仍然不对现象明明做了标定测量出来的毫米值和实际用卡尺量的对不上差个百分之几。原因标定用的标准件尺寸输入错了或者标定时的图像和测量时的图像分辨率不一致。VisionPro 的标定是绑定图像分辨率的如果换了相机或改了 ROI标定系数就失效了。解决重新标定并且确认标定时的图像采集参数和测量时完全一致。标定完成后用另一个已知尺寸的零件验证验证通过再上产线。5.2 硬币计数偶尔多一个或少一个现象同一堆硬币跑十次有一次数量不对多一个或少一个。原因多一个是把反光点或灰尘当成了硬币少一个是两枚硬币粘连没分开。这两种情况都跟阈值和面积过滤有关。解决先把面积下限提高滤掉小噪点再用圆拟合的半径范围限制把不是圆的东西排除。如果还不行检查光源是否有频闪频闪会导致某几帧图像亮度突变。5.3 骰子点数在 1 和 2 之间跳现象同一颗骰子有时候识别成 1 点有时候识别成 2 点。原因1 点的斑点比较大2 点的两个斑点比较小。如果阈值卡在斑点边缘的灰度上1 点的斑点可能被分割成两个小区域就变成 2 点了。解决把阈值往暗的方向调让斑点完整分割或者用形态学闭运算把断裂的斑点连起来。另外面积下限不要设太高否则小斑点会被滤掉。5.4 联合 C# 硬触发时图像丢帧现象用 C# 联合 VisionPro 做硬触发采集偶尔丢帧导致计数结果对不上。原因硬触发的信号和相机曝光没对齐或者 C# 的事件处理耗时太长错过了下一帧。解决把图像采集放在独立线程事件处理只做入队不做耗时计算。硬触发信号用示波器确认和曝光信号的时序关系必要时加延时。VisionPro 的 CogAcqFifoTool 支持硬触发配置时注意触发模式和超时设置。5.5 显示结果滞后一帧现象操作员看到的测量值总是上一次的结果和当前图像对不上。原因显示刷新在工具运行之前执行了或者用了异步刷新但没等结果就更新了。解决确保Run()完成并检查Results有效后再更新图形。如果用了多线程用Invoke回到 UI 线程更新并且加一个「结果版本号」判断避免旧结果覆盖新结果。6. 把三个案例串成一条产线检测思路单独跑通硬币统计或骰子点数只能算练手。真正有价值的是把这三个案例的思路串起来做成一条能落地的检测流程。我一般会按「定位 → 测量 → 分类计数 → 结果输出」四步来组织每一步对应 VisionPro 里的不同工具组合。定位用 CogPMAlignTool 或 Blob 找最大区域目的是把 ROI 锁定在目标上。测量用 CogCaliperTool 或 CogFindLineTool输出物理尺寸。分类计数用 CogBlobTool 加圆拟合或斑点分析输出数量和类别。结果输出用 CogGraphicLabel 叠加到显示控件同时通过 C# 把数据推给 PLC 或数据库。下面这张表是我常用的工具与场景对应关系可以直接抄场景主工具关键参数常见坑零件尺寸测量CogCaliperToolContrastThreshold、FilterHalfSize标定失效、边缘跳变硬币统计CogBlobTool CogFindCircleToolThreshold、Area、CircleRadius粘连、反光误检骰子点数统计CogBlobTool CogPMAlignToolThreshold、Morphology、AcceptThreshold斑点断裂、阈值漂移硬触发采集CogAcqFifoToolTriggerMode、Timeout丢帧、时序不对齐验证方法上我习惯用「同一批样本跑 100 次」的方式看稳定性。硬币统计要求 100 次计数完全一致骰子点数要求 100 次识别结果和人工核对一致零件尺寸要求 100 次测量的标准差小于公差的三分之一。达不到就回去调参数不要靠「大概能用」蒙混过关。进阶用法里VisionPro 的二次开发可以把你调好的工具链封装成一个自定义工具用 C# 写成 DLL在 QuickBuild 里像原生工具一样拖拽使用。这样产线换型时只需要改参数不用重新搭流程。我一般会把阈值、面积范围、标定系数做成输入参数操作员在界面上就能调不用进脚本。最后说个我自己的习惯每调好一个案例我都会把参数截图和当时的图像存一份标注日期和光源条件。因为过两个月再回头看你绝对想不起来当时为什么把阈值设成 80 而不是 75。这个习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表