
简介这份资源是面向机器视觉初学者与工业检测开发者的VisionPro案例合集围绕尺寸测量、目标计数与瑕疵检测等典型任务帮助读者理解视觉软件在自动化产线与质量控制中的落地方式。包内共930个文件以650张jpg与40张bmp图像作为样本素材配合76个cs源码、25个vpp工程文件及40个resx资源文件构成可运行的案例工程另有少量py脚本、dll与exe辅助程序压缩包约65.75MB。案例覆盖零件尺寸测量与显示、硬币统计、骰子点数统计、孔位数量统计、零件与啤酒盖瑕疵检测、书签类型检测、手机电池正反面识别、车牌识别、陶瓷釉面与地面裂痕标注、杂志页排序、药物胶囊瑕疵检测等场景。已有127人学习读者可借助现成图像与工程文件快速复现测量、计数、识别与标注流程对照源码理解工具链配置与参数调试思路适合作为课程设计、项目预研与技能进阶的参考素材。1. 从一堆硬币和骰子说起这套 VisionPro 案例到底能跑出什么结果很多人第一次打开 VisionPro 的作业编辑器面对满屏的 ToolGroup、CogToolBlock 和一堆输入输出端子脑子是懵的。教程看了一堆真到产线上要测一个零件的孔径、统计一盒硬币的枚数、数出骰子的点数还是不知道从哪下手。这套案例的价值就在这它不跟你讲抽象概念直接拿三个典型场景——零件尺寸测量与显示、硬币统计、骰子点数统计——把 VisionPro 从取像到工具链搭建再到结果输出的完整流程跑通。适合刚接触康耐视 VisionPro 的视觉工程师、需要快速验证方案可行性的设备集成商以及正在做 VisionPro 二次开发、准备联合 C# 做硬触发的开发者。你拿到的不只是几个作业文件而是一套可以照着改、照着调的参考实现。2. 零件尺寸测量与显示从取像到结果标注的完整链路2.1 为什么尺寸测量优先用卡尺和找圆工具零件尺寸测量是机器视觉里最基础也最容易翻车的场景。VisionPro 提供的测量工具不少但针对规则零件的长度、宽度、孔径、圆心距最稳的组合是CogCaliperTool卡尺工具加CogFindCircleTool找圆工具。卡尺工具的本质是在一条搜索线上做灰度投影找到边缘对然后算出边缘之间的距离。它的优势是速度快、参数直观缺点是抗噪能力有限遇到毛刺或反光会跳边。找圆工具则是在指定环形区域内做边缘点提取再用最小二乘法拟合圆。对于硬币、轴孔这类圆形特征找圆比卡尺更合适因为它能利用整圈边缘信息对局部干扰有抑制作用。选型逻辑很简单直线距离用卡尺圆直径和圆心用找圆复杂轮廓用 CogFindLineTool 或 CogFindEllipseTool。这套案例里零件尺寸测量部分就是按这个思路搭的先定位零件再分别用卡尺和找圆提取关键尺寸。2.2 搭建测量作业的实操步骤下面以测量一个带圆孔的矩形零件为例说明在 VisionPro 作业编辑器里的操作顺序。假设你已经完成相机连接和标定标定文件已经加载。# 步骤一新建作业并加载标定 # 在 VisionPro QuickBuild 中新建 Job # 右键 Image Source - 选择相机或图片文件夹 # 右键 Calibration - 加载 .cal 标定文件 # 注意标定文件必须与当前相机分辨率和镜头焦距匹配# 步骤二用 CogPMAlignTool 做零件定位 # 这是整个测量链路的前置条件定位不准后面全废 pm_align CogPMAlignTool() pm_align.Pattern.TrainImage input_image pm_align.Pattern.Origin.TranslationX 320 # 模板原点X按实际ROI调整 pm_align.Pattern.Origin.TranslationY 240 # 模板原点Y pm_align.RunParams.AcceptThreshold 0.7 # 接受阈值低于此值判定定位失败 pm_align.RunParams.ApproximateNumberToFind 1 pm_align.Run() # 逻辑说明PMAlign 基于归一化灰度相关做模板匹配 # 参数说明AcceptThreshold 设 0.7 是经验值光照稳定可降到 0.6光照波动大要提到 0.8# 步骤三用 CogCaliperTool 测量矩形宽度 caliper CogCaliperTool() caliper.Region CogRectangleAffine() # 搜索区域需根据PMAlign结果动态跟随 caliper.RunParams.EdgeMode CogCaliperEdgeModeConstants.SingleEdge caliper.RunParams.Edge0Polarity CogCaliperPolarityConstants.DarkToLight caliper.RunParams.ContrastThreshold 15 # 对比度阈值太低会抓到噪声 caliper.RunParams.FilterHalfSizeInPixels 2 # 滤波半宽抑制毛刺 caliper.Run() width caliper.Results[0].Width # 边缘对之间的距离单位像素 # 逻辑说明卡尺在搜索区域内沿投影方向找边缘对 # 参数说明ContrastThreshold 是关键一般设 10~30具体看灰度差# 步骤四用 CogFindCircleTool 测量圆孔直径 find_circle CogFindCircleTool() find_circle.RunParams.NumCalipers 20 # 卡尺数量越多拟合越稳但越慢 find_circle.RunParams.CaliperSearchLength 50 find_circle.RunParams.CaliperProjectionLength 30 find_circle.RunParams.CaliperSearchDirection CogFindCircleSearchDirectionConstants.InsideOut find_circle.RunParams.ExpectedCircularArc.CenterX 400 # 预期圆心可由PMAlign结果换算 find_circle.RunParams.ExpectedCircularArc.CenterY 300 find_circle.RunParams.ExpectedCircularArc.Radius 80 find_circle.Run() diameter find_circle.Results.GetCircle().Diameter # 逻辑说明在环形区域内均匀分布卡尺提取边缘点后拟合圆 # 参数说明NumCalipers 建议 15~30太少拟合不稳太多耗时# 步骤五结果标注与显示 # 在 CogToolBlock 的输出端创建 CogGraphicLabel 和 CogGraphicLine # 将测量值绑定到显示图形上 label CogGraphicLabel() label.Text fWidth: {width:.2f} px label.SetXY(100, 50) # 逻辑说明VisionPro 的显示层通过 CogGraphicCollection 管理 # 参数说明坐标单位与图像坐标系一致标定后可换算为毫米以上五步是尺寸测量的最小闭环。实际项目里还要加结果判定逻辑比如宽度公差 ±0.05mm超出就输出 NG 信号。这套案例的作业文件里已经把这些工具串好了你打开就能看到每个工具的 ROI 和参数配置改起来比从零搭快得多。2.3 标定与像素当量换算的注意点尺寸测量要输出物理单位标定是绕不过去的。VisionPro 的标定工具支持棋盘格和圆点靶标常见做法是用九点标定或棋盘格标定。九点标定适合平面测量操作简单但只校正平移和旋转不校正镜头畸变。棋盘格标定能输出更完整的相机参数适合高精度场景。像素当量的计算方式是标定后每个像素对应的物理尺寸。比如标定结果显示 1 pixel 0.02mm那测量出 500 像素就是 10mm。这里有个容易忽略的点标定时的镜头焦距、工作距离、光圈必须和实际测量时一致否则标定白做。我见过有人标定完动了光圈结果尺寸整体偏了 3%查了半天才发现是光圈变了。提示标定文件加载后在 CogToolBlock 里通过 Calibration 属性关联到测量工具工具输出的结果会自动带物理单位。如果没关联输出的还是像素值。3. 硬币统计Blob 分析与形态学处理的组合拳3.1 Blob 分析为什么是硬币统计的首选硬币统计的核心需求是数出视野里有多少枚硬币可能还要区分面值。VisionPro 里做这类计数首选CogBlobTool斑点分析工具。Blob 的原理是先做阈值分割把前景从背景里分出来然后对连通区域做标记和统计。硬币和背景的灰度差通常很明显阈值分割很容易得到干净的二值图。但直接阈值分割有个问题硬币表面的花纹和反光会导致区域内部出现空洞或者相邻硬币粘连。这时候就需要形态学处理来补救。VisionPro 的 CogBlobTool 内置了形态学操作包括腐蚀、膨胀、开运算、闭运算。开运算先腐蚀后膨胀能去掉小噪点闭运算先膨胀后腐蚀能填补内部空洞。硬币统计一般用闭运算填洞再用开运算分离轻微粘连。3.2 硬币统计的完整参数配置# 步骤一配置 CogBlobTool 的阈值 blob CogBlobTool() blob.Region CogRectangleAffine() # 搜索区域覆盖整个料盘 blob.RunParams.SegmentationMode CogBlobSegmentationModeConstants.HardFixedThreshold blob.RunParams.Threshold 128 # 硬阈值硬币亮背景暗时用这个 blob.RunParams.Polarity CogBlobPolarityConstants.LightBlobs # 逻辑说明硬阈值适合光照稳定的场景光照不均时改用自适应阈值 # 参数说明Threshold 需要根据实际灰度直方图调整一般在双峰谷底取值# 步骤二形态学处理填补空洞和分离粘连 blob.RunParams.MorphologyOperations CogBlobMorphologyConstants.Open blob.RunParams.MorphologyKernelSize 3 # 核大小3x3 适合小噪点 blob.RunParams.MorphologyOperations CogBlobMorphologyConstants.Close blob.RunParams.MorphologyKernelSize 5 # 闭运算核稍大填洞更彻底 # 逻辑说明先开后闭是常见组合先去掉噪点再填洞 # 参数说明核大小必须是奇数太大容易把相邻硬币合并# 步骤三面积过滤排除非硬币区域 blob.RunParams.AreaThresholdLow 500 # 最小面积小于此值不算硬币 blob.RunParams.AreaThresholdHigh 50000 # 最大面积大于此值可能是粘连团 blob.Run() coin_count blob.Results.Count # 逻辑说明面积过滤是最有效的去伪手段 # 参数说明面积阈值需要根据实际硬币像素面积设定先跑一遍看直方图# 步骤四输出统计结果 for i in range(blob.Results.Count): area blob.Results[i].Area cx blob.Results[i].CentroidX cy blob.Results[i].CentroidY # 可以在这里做面值分类比如按面积大小区分 # 逻辑说明遍历每个 Blob 的结果提取面积和质心 # 参数说明CentroidX/Y 是质心坐标可用于后续定位或标注这套流程跑下来一盒硬币的枚数基本能数准。但有几个坑要注意硬币重叠时 Blob 会合并成一个大区域面积过滤能筛掉一部分但两枚完全重叠的硬币是分不开的。这时候要么用模板匹配逐个找要么用分水岭算法做分割。VisionPro 的 Blob 工具不直接支持分水岭需要自己写脚本或用 CogWatershedTool如果有授权。3.3 硬币粘连与重叠的处理策略粘连是硬币统计里最头疼的问题。轻微粘连可以用开运算分离但开运算的核大小很难调核太小分不开核太大硬币本身被腐蚀没了。我的经验是先用小核开运算试如果还粘连改用距离变换加分水岭。VisionPro 里可以通过 CogImageConvertTool 把二值图转成灰度距离图再用 Blob 的软阈值分割。另一个策略是模板匹配。如果硬币大小一致用 CogPMAlignTool 训练一个硬币模板然后设置 ApproximateNumberToFind 为较大值让工具在图像里找所有匹配。模板匹配对重叠的鲁棒性比 Blob 好因为它是基于灰度相关不是基于连通性。缺点是速度慢硬币多的时候耗时明显。注意模板匹配的 AcceptThreshold 不能设太低否则会在背景上误匹配。硬币统计场景建议不低于 0.65具体看硬币纹理丰富程度。4. 骰子点数统计从找点到分类的完整实现4.1 骰子点数的识别逻辑骰子点数统计比硬币统计复杂一层因为不仅要找到骰子还要数出每个骰子上的点数。骰子的点数就是黑色圆点背景是白色或彩色。识别逻辑分两步先定位每个骰子的区域再在每个区域内统计黑点数量。定位骰子可以用 Blob 分析因为骰子通常是白色方块和背景有对比。找到骰子区域后在每个区域内再做一次 Blob 分析这次找的是黑色圆点。黑点的面积范围比较固定用面积过滤就能排除噪点。最后统计每个骰子区域内的黑点数量就是点数。这套案例里的骰子点数统计作业就是这么搭的。它用了一个 CogBlobTool 找骰子然后用 CogToolBlock 对每个骰子区域做循环处理内部再跑一个 CogBlobTool 找点。这种嵌套结构在 VisionPro 里很常见关键是区域传递要正确。4.2 嵌套 Blob 的实现与参数传递# 步骤一外层 Blob 找骰子 outer_blob CogBlobTool() outer_blob.Region CogRectangleAffine() outer_blob.RunParams.SegmentationMode CogBlobSegmentationModeConstants.HardFixedThreshold outer_blob.RunParams.Threshold 100 outer_blob.RunParams.Polarity CogBlobPolarityConstants.LightBlobs outer_blob.RunParams.AreaThresholdLow 2000 # 骰子面积下限 outer_blob.RunParams.AreaThresholdHigh 20000 outer_blob.Run() # 逻辑说明骰子是亮区域用 LightBlobs 提取 # 参数说明面积阈值根据骰子实际像素面积设定# 步骤二对每个骰子区域做内层 Blob 找点 for i in range(outer_blob.Results.Count): # 获取第 i 个骰子的边界框 bbox outer_blob.Results[i].BoundingBox # 创建内层 Blob区域设为该骰子的边界框 inner_blob CogBlobTool() inner_blob.Region CogRectangleAffine() inner_blob.Region.SetXYWidthHeight(bbox.CenterX, bbox.CenterY, bbox.Width, bbox.Height) inner_blob.RunParams.SegmentationMode CogBlobSegmentationModeConstants.HardFixedThreshold inner_blob.RunParams.Threshold 60 # 黑点阈值比骰子阈值低 inner_blob.RunParams.Polarity CogBlobPolarityConstants.DarkBlobs inner_blob.RunParams.AreaThresholdLow 20 # 点面积下限 inner_blob.RunParams.AreaThresholdHigh 200 # 点面积上限 inner_blob.Run() dot_count inner_blob.Results.Count # 逻辑说明内层 Blob 在骰子区域内找暗点 # 参数说明DarkBlobs 提取暗区域面积阈值排除噪点# 步骤三输出每个骰子的点数 print(fDice {i1}: {dot_count} dots) # 可以在这里加判定逻辑比如点数不在 1~6 范围内就报警 # 逻辑说明遍历所有骰子输出点数 # 参数说明dot_count 就是点数正常范围 1~6这段代码的关键在于区域传递。外层 Blob 找到的每个骰子其边界框作为内层 Blob 的搜索区域。如果区域传递错了内层 Blob 会在整个图像里找点结果全乱。VisionPro 的 CogToolBlock 支持这种嵌套但需要手动配置输入输出端子把外层的 Results 逐个传给内层。4.3 点数识别的鲁棒性优化骰子点数识别最容易翻车的地方是光照不均。如果骰子表面有反光黑点可能被反光淹没阈值分割就分不出来了。解决办法有两个一是用环形光源或同轴光源减少反光二是在软件里用自适应阈值代替硬阈值。VisionPro 的 Blob 工具支持相对阈值和自适应阈值相对阈值是根据图像灰度均值动态调整对光照变化有一定适应能力。另一个问题是骰子倾斜。如果骰子不是正对相机黑点会变成椭圆面积会变化。面积阈值设得太死会漏掉倾斜的点。这时候可以把面积阈值范围放宽或者用圆度过滤代替面积过滤。VisionPro 的 Blob 结果里有圆度属性可以设一个圆度下限比如 0.7排除掉不规则形状。提示骰子点数统计的准确率高度依赖光源。如果条件允许用白色漫射光源从侧面打光让黑点形成清晰的暗区比正面打光效果好得多。5. 避坑与排查这三个案例里最容易翻车的地方5.1 定位工具失败导致后续全错现象PMAlign 定位失败后续卡尺和找圆的 ROI 全部偏移测量值完全不对。原因模板训练时用的图像和实际运行时差异太大比如光照变了、零件换了批次、模板原点设偏了。解决模板训练时多采几张不同光照的图像用 CogPMAlignTool 的多模板训练功能。AcceptThreshold 不要设太高0.7 左右比较稳。另外在 ToolBlock 里加一个判定定位失败就跳过后续工具输出报警而不是错误数据。5.2 标定文件与实际工况不匹配现象测量值整体偏大或偏小重复性差。原因标定时的镜头焦距、工作距离、光圈和实际测量时不一致或者标定板没有放平。解决标定完成后锁定镜头光圈和焦距用胶带固定。标定板要贴合测量平面倾斜会导致像素当量不均匀。每次更换镜头或调整工作距离后必须重新标定。5.3 Blob 阈值设置不当导致计数错误现象硬币统计多算或少算骰子点数识别错误。原因阈值设得太高暗区域被漏掉阈值设得太低背景噪点被算进去。解决先用 CogHistogramTool 看灰度直方图找双峰之间的谷底作为阈值。如果直方图没有明显双峰说明光照不均需要改光源或改用自适应阈值。面积阈值也要根据实际像素面积设定不要凭感觉填。5.4 形态学核大小选错导致硬币合并或消失现象相邻硬币被合并成一个大 Blob或者硬币被腐蚀没了。原因开运算核太大硬币本身被腐蚀核太小粘连分不开。解决先用 3x3 核试不行再逐步加大到 5x5、7x7。每次调整后看 Blob 结果的数量和面积分布。如果硬币本身很小开运算要慎用改用距离变换加分水岭。5.5 嵌套 Blob 区域传递错误现象骰子点数统计结果全是 0 或者异常大。原因内层 Blob 的区域没有正确绑定到外层 Blob 的每个结果上导致内层在整个图像里找点。解决在 CogToolBlock 里检查端子连接确保外层 Results 的每个元素都传给了内层 Blob 的 Region 输入。可以用 CogToolBlock 的调试功能单步运行看每一步的区域是否正确。6. 进阶技巧把这三个案例串成一套可复用的检测框架这三个案例单独跑通不难难的是把它们整合成一个可复用的检测框架。我的做法是建一个 CogToolBlock把定位、测量、计数、分类做成独立的子 ToolBlock通过输入输出端子串联。这样换产品时只需要改子 ToolBlock 的参数不用动整体结构。具体来说顶层 ToolBlock 的输入是图像输出是检测结果结构体。子 ToolBlock 包括定位模块PMAlign、尺寸测量模块卡尺找圆、计数模块Blob、分类模块按面积或圆度分类。每个子模块都有独立的输入图像和 ROI 参数通过顶层传递。# 顶层 ToolBlock 的伪代码结构 class InspectionToolBlock: def __init__(self): self.align CogPMAlignTool() self.measure CogCaliperTool() self.find_circle CogFindCircleTool() self.blob CogBlobTool() def run(self, image): # 第一步定位 self.align.InputImage image self.align.Run() if not self.align.Results.Count: return {status: ALIGN_FAIL} # 第二步根据定位结果更新 ROI pose self.align.Results[0].GetPose() self.measure.Region self._transform_roi(base_roi_measure, pose) self.find_circle.RunParams.ExpectedCircularArc self._transform_circle(base_circle, pose) # 第三步执行测量和计数 self.measure.Run() self.find_circle.Run() self.blob.Run() # 第四步汇总结果 return { status: OK, width: self.measure.Results[0].Width, diameter: self.find_circle.Results.GetCircle().Diameter, count: self.blob.Results.Count } # 逻辑说明顶层 ToolBlock 负责调度和结果汇总 # 参数说明_transform_roi 和 _transform_circle 是根据定位姿态做坐标变换的辅助方法这套框架的好处是扩展性强。加一个新测量项只需要在顶层加一个子工具在 run 方法里加一行调用。换产品时改 ROI 和阈值参数就行不用重新搭作业。验证方法也很直接用同一张图跑两遍看结果是否一致用不同光照的图跑看定位是否稳定用已知尺寸的标准件跑看测量误差是否在公差内。我一般会准备一组测试图包括正常图、光照偏暗图、零件偏移图、硬币重叠图每次改完参数都跑一遍确认没有回归。从那以后我每次搭新作业都强制先跑一遍定位稳定性测试再跑测量重复性测试最后才调参数。这个习惯帮我省了很多返工的麻烦。希望帮到你。本文还有配套的精品资源点击获取