十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Halcon工业质检实战:5个案例搞定尺寸测量与缺陷检测

Halcon工业质检实战:5个案例搞定尺寸测量与缺陷检测 机器视觉这行干了快十年接过不少产线上的质检需求接触最多的工具就是Halcon。每次带新人总有人问我Halcon到底怎么才能算入门我一般会回答别抱着教程啃算子文档直接拿真实项目去磨磨出来几个完整案例比看十遍官方示例都管用。所以这篇内容我不写那些软件安装、环境配置的基础铺垫直接给你5个我用Halcon落地过的工业质检案例覆盖尺寸测量、划痕检测、字符识别、装配完整性检查和颜色分拣这几类产线上最常见的场景。每个案例都有完整思路、可用代码和必须注意的坑。代码是Halcon脚本你装了HDevelop就能直接跑通包一些自己的图就能验证效果。先说一个所有人都会踩的通病拿到一张图不管三七二十一先跑一堆二值化、找边缘然后发现效果不行开始怀疑Halcon不行或者自己的图不行。实际上工业质检项目的成败在动手写代码前就已经决定了。你选什么光源、什么相机、什么镜头直接决定了后面算法难度差多少个量级。这不是鸡汤是我被现场折磨无数次以后得出来的结论。1. 一个质检项目在写代码之前你至少要搞定的三件事我接触过很多失败的方案问题不全出在算法上反而是前面的成像环节就埋了雷。Halcon再强它也是处理图片的如果图片本身没有把缺陷拍出来后续一切算法都是空中楼阁。第一件事选对光源角度。产线上打光无外乎几种高角度光、低角度光、同轴光、背光。高角度光适合平坦表面的特征增强低角度光能凸显表面凹凸纹理同轴光适合高反光平面背光能形成高对比度轮廓剪影。举个例子你要检测金属表面的划痕如果用高角度环形光划痕可能完全看不到因为光线被平面反射走了。这时候改用低角度光让光线贴着表面照射划痕的漫反射才会被相机捕捉到。第二件事定好相机和镜头的配合。这涉及一个基础计算——分辨率。假设你的视野是50mm宽需要检测的最小缺陷是0.1mm那么你至少需要50/0.1500个像素来覆盖这个视野。考虑到算法上一般希望缺陷区域至少有3×3像素才能被稳定提取所以实际需要500×31500像素宽的分辨率。用200万像素1600×1200的相机才勉强够用如果再考虑噪点和边缘过渡因素500万像素会更稳妥。第三件事确认产品定位方式。如果每次来料位置偏差很大你就要在算法里做模板匹配来找ROI如果定位机构能保证位置重复精度在几个像素以内那你可以直接用固定ROI剪裁速度会快不少。实际项目中我很少依赖纯机械定位因为产线上的震动、夹具磨损是常态算法层面做一次快速模板匹配更省心。这三件事都没问题了才轮到Halcon上场。2. 案例一轴承外圈尺寸测量——亚像素找边与卡尺工具第一个案例从最常见的尺寸测量说起。你拿到一张轴承外圈的图像需要测量外径、内径、沟道位置这几个关键尺寸公差要求是±0.01mm。如果直接对整幅图做边缘提取再拟合圆你会发现结果忽大忽小稳定性很差。原因是边缘像素级提取的精度不够。像素是离散的一个边缘往往跨越2~3个像素单纯找灰度跳变最大点精度最多到1个像素。如果你的标定关系是0.05mm/pixel1个像素的误差就是0.05mm公差±0.01mm根本没法满足。Halcon里解决这个问题有专门的卡尺工具思路在已知边缘附近取一个矩形区域沿着矩形短边方向提取边缘点用灰度插值把边缘定位到亚像素精度。它的原理相当于在边缘过渡带上拟合一条曲线找到灰度变化最快的极值点这个点可以是小数像素坐标比如边缘在157.3像素的位置。核心代码思路如下* 读取图像 read_image (Image, bearing_outer_ring.png) * 预先标定好的像素当量单位mm/pixel * 这里假设标定结果为0.048 mm/pixel PixelCalib : 0.048 * 创建一个卡尺测量对象在指定ROI内找边缘 * 输入参数图像、圆心初始坐标、起始角度、终止角度、测量长度、测量宽度等 * 这里只做示意实际参数可以跑measure_pos帮助文档理解 * 需要先设定一个环形ROI gen_circle (Circle, CenterRow, CenterCol, Radius) reduce_domain (Image, Circle, ImageReduced) * 使用edges_sub_pix提取亚像素边缘亚像素轮廓 edges_sub_pix (ImageReduced, Edges, canny, 1.5, 20, 40) * 用fit_circle_contour_xld拟合圆得到亚像素圆心坐标和半径 fit_circle_contour_xld (Edges, algebraic, -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder) * 计算出直径像素值 DiameterPx : 2 * Radius * 换算成物理尺寸 DiameterMm : DiameterPx * PixelCalib这里有个关键参数要解释canny, 1.5, 20, 40。1.5是高斯平滑系数20和40是滞后阈值的低阈值和高阈值。低阈值决定哪些边缘点可以作为候选高阈值决定哪些强边缘点被保留。这个组合不是拍脑袋定的需要看图像的边缘梯度直方图来调整。如果边缘和背景对比度很好阈值可以设高一些减少干扰边缘如果对比度一般阈值要降低但干扰点也会变多。实际调试时我习惯先用低阈值20然后看提取出的边缘是否完整再看有没有多余碎边。fit_circle_contour_xld里有algebraic和geometric两种拟合方法。geometric对离群点更鲁棒但速度稍慢algebraic速度快适合边缘质量比较好的场景。产线上如果来料表面有油污或轻微磕碰我会优先用geometric多花零点几毫秒换稳定性值。踩坑提示edges_sub_pix提取出的轮廓里常常混入背景里的干扰边缘比如夹具边缘、工作台划痕之类。所以一定要在拟合前先做轮廓筛选。常用的方法是用select_contours_xld按长度、按轮廓到圆心的距离范围来过滤。比如轴承外圈边缘的长度特征非常明显可以先按长度筛掉那些短小的碎轮廓再用select_shape_xld之类限制在预期的半径范围内这样拟合圆时就不会被杂散边缘带偏。这个案例跑完后建议做一个批量验证准备20~30张不同位置、不同光照条件下的图像统计测量结果的均值和标准差。如果标准差超过公差范围的1/3说明算法稳定性还不够需要回到图像质量或者边缘提取参数上继续调。3. 案例二手机屏幕划痕检测——顶帽变换与动态阈值配合第二个案例是手机盖板玻璃或保护片上的划痕检测。这个场景的特点是划痕目标和背景的对比度很低而且背景本身有纹理光照也不均匀。如果直接用固定阈值二值化要么把背景纹理误检成缺陷要么漏掉真正的划痕。这类问题的经典解法是形态学顶帽变换。它的原理很简单先用形态学开运算先腐蚀后膨胀估计出背景的灰度分布然后用原始图像减去这个背景估计剩下的就是那些比背景暗或亮的局部特征。开运算的效果可以被想象成熨斗——它在图像上滑过把那些比结构元素小的凸起细节磨平。结构元素尺寸设多大决定了哪些细节被当做背景保留哪些被凸显为前景。划痕一般几个像素宽背景纹理可能在几十个像素尺度所以结构元素选一个比划痕宽、比背景纹理小的尺寸比如15×15的圆形结构元素。* 读取图像 read_image (Image, screen_scratch.png) * 转灰度 rgb1_to_gray (Image, GrayImage) * 顶帽变换原图减开运算结果提取暗划痕 gray_tophat (GrayImage, ImageTopHat, 15, 15) * 动态阈值分割 * 先用均值滤波器估计局部背景灰度 mean_image (ImageTopHat, ImageMean, 31, 31) * 用原始顶帽结果减局部背景设定偏移量找出显著暗区域 dyn_threshold (ImageTopHat, ImageMean, RegionDyn, 8, dark) * 连通域分析去掉小块噪点 connection (RegionDyn, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, area, and, 30, 99999) * 将区域转换成轮廓方便后续可视化或标记 gen_contour_region_xld (SelectedRegions, Contours, border)这个方案里有两个参数值得仔细说明。第一个是顶帽变换的结构元素大小15×15。这个值需要根据图像里划痕的宽度来定。划痕一般2~5像素宽背景的细微纹理可能是10像素以上尺度。如果结构元素设太小比如3×3会把背景纹理也当成前景保留顶帽后得到一堆噪点如果设太大比如50×50开运算估计的背景不够精确在光照剧烈变化的边缘区域容易出现假阳性。第二个是dyn_threshold里的偏移量8。这个偏移量表示比局部背景暗至少8个灰度级才被认为是前景。如果设太小光线不均匀导致的暗斑会被误检如果设太大浅划痕可能漏检。调试时的技巧是先用一个较大偏移量保证没有误检再慢慢降低直到真实划痕刚好被完整检出这个临界值附近再留一点余量。说一下这条链路里为什么要加mean_image dyn_threshold而不是直接threshold。因为即使做了顶帽变换图像中依然可能存在全局亮度不均匀的残留比如玻璃边缘的渐晕。直接设定一个全局固定阈值在亮区和暗区效果会差很多。dyn_threshold是自适应阈值每个像素的比较基准是自己邻域的均值这样对光照不均就不敏感。这个方案在产线上用的时候还会遇到一个现实问题——划痕并不总是暗于背景的。某些角度下划痕在图像里看起来是亮的。解决方案是同时对亮暗两个方向做检测要么用gray_tophat和black_tophat各做一次要么在dyn_threshold的LightDark参数里选择light和dark分别处理。跑完这个案例我建议你做一个最简单的误检率验证拿100张合格品图像跑一遍算法统计误报警的数量。工业现场要求误检率越低越好因为每次误报都要人工去确认成本很高。如果误检在千分之一以上就需要增加分类器做二次确认比如用Halcon的MLP分类器或深度学习方法第一步快速找可疑区域第二步分类确认。4. 案例三PCB焊点桥连检测——连通域分析的快与慢第三个案例是PCB板上的焊点桥连检测。所谓桥连就是两个相邻焊点之间的焊锡连在了一起造成短路。这是SMT产线比较常见又特别需要防住的缺陷。PCB板图像的特点是背景复杂——有绿色阻焊层、白色丝印、各种走线。焊点在图像里通常是圆形的金属亮斑。桥连检测的基本思路是先定位所有焊点的位置通常用模板匹配或者基于Gerber文件的先验坐标然后在每个焊点周围开一个小ROI检查这个ROI内是否有异常连接。在Halcon里最快的定位方式是find_ncc_model或find_shape_model。NCC基于归一化互相关匹配对光照变化不敏感形状匹配基于轮廓特征对遮挡和旋转更鲁棒。焊点是圆形但来料角度可能有细微偏差所以我一般用find_shape_model创建圆形模板允许小角度旋转这样即使板子没放正也能准确定位。定位好焊点后有两种检查桥连的思路。思路一是基于区域的连通域分析。把焊点区域二值化出来后对每个焊点区域做膨胀然后看膨胀后的区域是否和相邻焊点的膨胀区域交叠。如果两个焊点之间的间隙被焊锡填满膨胀后它们会连成一片连通域数量就会减少或者单个连通域的面积会异常增大。* 假设已经通过模板匹配拿到了两相邻焊点的中心坐标 * 生成两个焊点的小ROI gen_circle (ROI1, Row1, Col1, 30) gen_circle (ROI2, Row2, Col2, 30) * 在ROI内做阈值分割提取出焊锡区域 threshold (Image, RegionBright1, 100, 255) * 分别提取两个焊点的连通域 connection (RegionBright1, Connected1) * 检查最大连通域的面积是否超过正常焊点面积的1.5倍 area_center (Connected1, Area1, RowA1, ColA1) * 如果面积异常就判定为桥连这种方法的快在于纯区域运算不涉及复杂特征计算但它对图像质量要求较高要求焊点与背景有明显灰度差。如果板子表面有残胶或者反光不均二值化效果会很差误检就来了。思路二是基于形态学的连线检测。先用dilation_circle对两个相邻焊点区域分别做膨胀膨胀半径略小于焊点间距的一半然后用intersection求两个膨胀区域的重叠区。如果重叠区的面积超过一个阈值说明桥连发生了。这种方法在逻辑上更贴近两焊点之间异常导电连接这一物理定义误判率更低因为即使反光不均导致单个焊点提取不完整只要中间真有桥连两个膨胀区依然会重叠。切实用中还有一种更工程化的做法就是检查连通域面积是否超过单个焊点面积的1.5倍这个判据。因为一个正常的焊点区域面积是相对固定的如果桥连发生了焊锡把两个焊点连通对应的连通域面积会接近两个焊点之和远超1.5倍阈值。这里我要多说一句关于连通域分析的优化。当PCB上焊点数量很多比如几百个所有焊点一步到位整体做connection运算量会比较大。实际做法是把整幅图先缩小检查或者按区域分块处理每块只处理10~20个焊点。这样单次运算量小处理速度就会快很多还能方便地做并行化。5. 案例四药瓶标签字符识别与缺陷检测——OCR与区域筛选第四个案例是药瓶标签上的生产日期字符识别和印刷缺陷检测。字符识别这块Halcon有专门的OCR工具但你千万不要以为装个OCR工具就万事大吉。工业字符识别的难点在于字符可能印在曲面瓶身上有弧度变形可能有反光可能有污渍遮挡。先讲字符识别怎么做。如果字符位置相对固定最快的方案是read_ocr_class_mlp加载一个预训练模型配合do_ocr_multi_class_mlp来完成识别。但预训练模型对字体、大小、光照很敏感实际项目里几乎都要针对自己的字体做再训练或者重新训练。你需要采集至少100张包含所有目标字符的样本图手动标注字符区域生成一个.omc训练文件可以用Halcon的OCR Training Tool来做然后训练一个MLP分类器。更简单一点的做法是用模板匹配。如果日期字符的字体、大小不变只是内容在变化你可以为每个字符建立模板库然后用find_shape_model逐个字符去找。这种方法对图像质量要求高但胜在训练简单不需要准备大量标注数据。再讲印刷缺陷检测。这个比字符识别更容易被忽略也比它更难——你要检测的不是字符是什么而是字符有没有印坏。常见的印刷缺陷有断笔、飞墨、重影。这些缺陷通常体现在字符区域内有多余的墨点或者笔画中断。我的做法是先做字符识别拿到每个字符的精确位置和内容然后建立一个标准字符模板——也就是说如果这瓶药的生产日期是20250513我电脑里就有一张对应字体的20250513标准图。然后把采集到的字符区域图像和标准图做差影。* 假设已经定位到字符区域CharRegion内容为20250513 * 读取对应的标准模板图 read_image (StandardImage, std_20250513.png) * 将实际字符图像和标准图对齐到同一坐标系 * 通过模板匹配找到实际图像中的偏移 find_shape_model (CharImage, CharModelID, 0, 0, 0.5, 0, 0.5, least_squares, 0, 0.9, RowMatch, ColumnMatch, AngleMatch, Score) * 用仿射变换把标准图配准到实际图像 vector_angle_to_rigid (0, 0, 0, RowMatch, ColumnMatch, AngleMatch, HomMat2D) affine_trans_image (StandardImage, ImageAligned, HomMat2D, constant, false) * 做差影 abs_diff_image (CharImage, ImageAligned, DiffImage) * 阈值分割出差异区域面积超过阈值则判为印刷缺陷 threshold (DiffImage, RegionDiff, 30, 255) area_center (RegionDiff, AreaDiff, RowDiff, ColDiff)这种差影方案的精度取决于配准的精度。如果图像有0.5像素的偏移边缘上就会产生一圈假差异。解决办法是用高斯滤波对两幅图做平滑把边缘差异模糊掉再比较滤波器的大小和宽容度需要反复调。另外提醒一下药瓶标签检测通常涉及字符内容校验。你可以把OCR结果和数据可追溯系统里的信息做比对比如系统里记录的批号是B2025051301OCR识别出的是B2025051301那么通过一旦不一致说明喷码设备出了问题需要报警停机。这种识别校验联动的架构在现场比单纯识别更有实际意义。6. 案例五装配完整性检查——形状匹配建立坐标系与ROI联动第五个案例做一个典型的装配完整性检查手机中框上需要贴6个螺母检测6个螺母是否全部到位位置是否正确。这类场景的特点在于产品是柔性放置的每次拍照的位置和角度都有偏差你不能用固定ROI去看。先建立基准坐标系。用产品上两个最稳定的特征——比如两个定位孔——来建立坐标系。然后用模板匹配找到每个螺母的位置将其坐标转换到基准坐标系下再和理论坐标比较偏差超过阈值就判为不合格。在Halcon里完整流程是这样* 第一步创建形状模板选两个孔作为基准 * 在模板图上框选第一个基准孔ROI gen_circle (BaseCircle1, BaseRow1, BaseCol1, 15) reduce_domain (ModelImage, BaseCircle1, ImageBase1) create_shape_model (ImageBase1, auto, -0.1, 0.2, auto, auto, use_polarity, auto, auto, ModelID1) * 第二步在待测图上找基准孔位置 find_shape_model (Image, ModelID1, -0.1, 0.2, 0.5, 1, 0.5, least_squares, 0, 0.9, RowFound1, ColFound1, AngleFound1, Score1) * 同理找第二个基准孔 find_shape_model (Image, ModelID2, -0.1, 0.2, 0.5, 1, 0.5, least_squares, 0, 0.9, RowFound2, ColFound2, AngleFound2, Score2) * 第三步根据两个基准孔的位置计算仿射变换矩阵 * 将模板图中两个孔的坐标与实际图中的坐标对应起来 vector_to_rigid (ModelBaseRow1, ModelBaseCol1, 0, RowFound1, ColFound1, 0, HomMat2D_1) vector_to_rigid (ModelBaseRow2, ModelBaseCol2, 0, RowFound2, ColFound2, 0, HomMat2D_2) * 实际项目中需要对两个孔的结果做加权平均或者最小二乘拟合得到最优HomMat2D * 这里简化为用第一个孔的结果但真实项目中必须综合两个孔位 * 第四步把模板中螺母的理论坐标用HomMat2D变换到实际图像坐标 affine_trans_point_2d (HomMat2D, NutRowModel[0], NutColModel[0], NutRowActual[0], NutColActual[0]) * 第五步在实际螺母坐标处取小ROI检测是否有螺母存在 gen_circle (NutROI, NutRowActual[0], NutColActual[0], 20) reduce_domain (Image, NutROI, ImageNutROI) * 螺母通常是一个亮圆或六角形可以通过阈值和形状特征确认 threshold (ImageNutROI, RegionNut, 80, 255) connection (RegionNut, ConnectedNut) select_shape (ConnectedNut, SelectedNut, area, and, 200, 99999) count_obj (SelectedNut, NumNutRegions) if (NumNutRegions 1) * 螺母缺失记为不合格 endif这里面的关键问题是标准模板图里的理论坐标怎么来。我的做法是在首件确认通过的产品图上手动标定每个螺母的中心坐标保存下来。之后产品每来一次就用仿射变换把标准坐标投影到新图像上。只要产品在治具内的位置变化是刚体变换平移旋转这个投影就很准确。如果产品本身有变形比如塑料件轻微翘曲导致螺母位置不是简单的旋转平移就能对齐的那就需要加一个小的搜索窗口。比如投影坐标在理想情况下应该在±1像素内但变形导致偏差可能到±10像素你就在投影点为中心、20×20的邻域内做一个小范围模板匹配这样既避免全局搜索带来的速度问题和误匹配又能容忍变形。我得强调一下这个案例里最容易出错的地方是模板匹配分数阈值的选择。find_shape_model里那个0.5的MinScore参数设太高可能找不到目标设太低会误匹配到相似纹理上。可以参考的做法是先设为0.8跑一批图看看最低分是多少然后取最低分低0.1~0.2作为实际阈值留出安全余量。7. 把代码从HDevelop挪到产线——C#集成和性能优化思路有了上面这些HDevelop脚本验证完算法可行性后紧接着的问题就是怎么接到产线上。实际工业项目很少直接在HDevelop里运行大多数是集成到上位机软件里用C#、C调用Halcon的算子库。当你使用C#时基本流程是把HDevelop里验证好的脚本导出成C#代码然后嵌入到你的WinForm或WPF项目里。Halcon的导出功能很强导出的代码基本可以直接编译但有几个注意事项。第一Halcon的HImage和HObject对象生命周期必须管理好。C#里虽然有垃圾回收但Halcon的对象是非托管资源量大时会导致内存泄漏。标准做法是用using语句或者在finally里调用.Dispose()。// C#调用Halcon典型片段 HImage image new HImage(); image.ReadImage(test.png); try { HRegion region image.Threshold(100.0, 255.0); HOperatorSet.Connection(region, out HRegion connectedRegions); // 处理... } finally { image.Dispose(); }第二性能优化。Halcon的HDevelop脚本是解释执行的导出到C#后是调用算子性能会好一些但如果你写的是循环里逐像素处理那就完全偏离了Halcon的使用方式。Halcon的性能优势建立在向量化、批量化的算子运算上尽量用整体图像运算代替循环遍历。比如要处理100个焊点不要写成for循环一个点一个点地处理而是想办法把100个点的ROI区域拼成一个区域组一次性交给算子算。第三多线程与相机采集的配合。产线上一般是相机采集线程和检测线程分离。相机采到一帧图放到缓冲队列检测线程取帧、执行Halcon检测、返回结果。Halcon的算子本身是线程安全的你可以放心地让多个工作线程同时做检测但要控制并发数因为Halcon的深度学习推理和部分复杂算子会比较占用CPU过多并发反而导致每个线程都慢整体吞吐量下降。实践上一个CPU核跑一个检测线程是比较合理的分配。第四结果的追溯与展示。产线质检系统不仅是报不良还要记录缺陷图像、保存检测数据、打印报表。Halcon的dump_window_image可以把窗口内容保存为图片write_image可以保存原图。这些接口在上位机集成时要设计好方便后面的质量追溯和产线分析。8. 案例之外的调试经验图像质量、参数鲁棒性与验收标准代码能跑通只是第一步一个真正能交给产线的检测方案要在调试阶段反复打磨三个维度图像质量、参数鲁棒性和验收标准。先说图像质量。很多新手拿到图就开始调算法调了半天发现怎么搞都不稳定。正确的顺序是先看图像——有没有反光、有没有过曝、有没有运动模糊。如果发现某个批次的产品图像比之前明显偏暗或偏亮第一时间不是改代码而是去检查光源是不是衰减了。工业光源用久了亮度会降低这是定期维护的问题但也说明算法里不能用死的阈值。所以高鲁棒性的方案里建议采集一小块无特征区域做动态亮度补偿或者干脆用dyn_threshold这类自适应方法尽量减少对绝对灰度值的依赖。再说参数鲁棒性。调试阶段你手里可能就几张图觉得参数调得挺好但一到产线跑几天各种你想象不到的情况就来了——来料批次换了表面状态、环境光因为窗户照射角度变化、偶尔有油污飞溅到产品表面。所以调参时不要过拟合到少数样本上。正确做法是至少准备50~100张覆盖各种正常波动范围的图把参数在这批图上跑一遍统计正确率。如果阈值参数变化±20%正确率仍然在99%以上这个方案才基本算稳定。最后是验收标准。工业客户最常问的是两个指标漏检率和误检率。漏检是最不能容忍的缺陷流出到客户端会造成客诉误检会降低产线效率和人工成本。所以要跟客户明确这个项目的验收标准是多少漏检率通常是万分之几以下、多少误检率一般是千分之几。有了明确指标你才知道算法该往哪个方向优化——是加分类器降误检还是加图像增强降漏检。另一个影响鲁棒性的细节是模板匹配中的极性参数。find_shape_model里的use_polarity表示匹配时要求边缘的明暗方向和模板一致ignore_global_polarity则允许整体反转比如本来是黑底白圆翻成白底黑圆也能匹配。如果产线上产品颜色深浅批次波动大建议用ignore_local_polarity它对局部反光变化更宽容但相应也会增加误匹配风险。这个参数值得你在调试时专门花时间对比测试。我自己在产线上被坑得最多的一次是一个手机中框的划痕检测项目。客户给的样品图上划痕特别清晰方案很快就通过了验证。结果一上产线发现同一个位置每天上午测和下午测结果不一样反复排查后才发现是窗户外的阳光角度变化导致的。后来给相机和光源加了遮光罩问题才解决。从那以后我每次做视觉方案第一件事就是问客户这个工位的光照环境固定吗有没有窗户有没有其他设备的光干扰这些问题问清楚了能帮你少走很多弯路。9. 从单点到系统视觉算法和产线节拍的匹配写到最后我想聊聊多数教程不会提到的点——算法性能和产线节拍的匹配。产线节拍简单说就是每件产品允许的检测时间。比如节拍是5秒一件意味着你必须在5秒内完成取图、检测、判定、输出结果的全流程。通常留给算法的只有2~3秒因为在传送带上还有运动、定位、触发的时间。因此算法选型有一个基本原则在满足精度要求的前提下优先选择计算量小的方案。能用区域分析Blob分析解决的就不上深度学习能用模板匹配解决的就不跑OCR能用粗定位缩小范围再细检测的就不做全图高精度的处理。Halcon里几个常见的性能优化手段这里一并列出来供你参考。图像降采样。检测大尺寸缺陷时不需要原始分辨率可以把图像缩小到1/4再处理速度快接近一个数量级而精度损失完全可以接受。缩小搜索范围。模板匹配前先用低分辨率做一次快速定位锁定大概位置后在原分辨率下只在锁定区域做精细匹配。这样匹配时间能压缩到原来的十分之一甚至更少。分区并行。把一个大图像按区域切块每个块丢给一个线程去处理最后汇总结果。在现代多核CPU上这个方法非常有效。Halcon有par_start等并行算子可以辅助实现不过前提是你的图像切块之间没有依赖关系。减少ROI数量。reduce_domain后再做算子的运算量远小于全图运算ROI能缩小就缩小。不要图省事对整幅图跑大算子的连续操作。如果你用的是Halcon的深度学习推理比如用apply_dl_model做缺陷分类GPU加速几乎是必需的。CPU推理一张图可能要几秒GPU能在几十毫秒内完成。不过引入GPU会增加成本和部署复杂度一般用在算法确实无法用传统方法解决的场景比如纹理非常复杂、缺陷形态不固定、客户要求极高的检出率的情况。写到这里5个案例已经全部复盘完毕。每个案例的代码片段都是从实际项目里提炼出来的核心思路和参数我都做了说明。你可以拿着它们换自己的图像去跑去调去理解每个算子、每个参数在真实场景里的意义。机器视觉这条路没有捷径唯一有效的路径就是多上手真实项目多踩坑再回来总结。希望这篇内容能帮你少踩一些坑把时间省下来用在真正有价值的事情上。
返回列表