做机器视觉项目这些年,我发现“检测定位角度”几乎是所有产线视觉需求里最常出现、也最容易出问题的一类。不管是PCB板定位、连接器插针方向、手机中框装配,还是晶圆缺口校准,本质都是在问同一个问题:工件相对于标准位置偏了多少、转了多大角度。今天这篇就以Halcon机器视觉实战中的一个典型单元——“检测定位角度”为切入点,完整过一遍从需求拆解、方案选型、算子参数调整到精度验证的整个过程。内容适合刚入门Halcon的视觉工程师,也适合常年蹲现场、需要对项目做快速复盘的朋友,希望能帮你少踩几个我踩过的坑。
1. 项目背景与需求拆解——“角度检测”到底在解决什么问题
1.1 为什么角度检测需求如此高频
自动化产线上几乎所有“抓取—放置—装配—检测”流程,都需要先回答三个问题:工件在哪、偏了多少、转了多少度。前两个是位置问题,第三个就是角度问题。很多设备之所以要上视觉,不是因为人眼看不见,而是因为人工目测角度误差太大、速度太慢。比如一块PCB板从上一工位皮带上滑下来,往往不是四平八稳的,可能偏了3到5度;这时候机械手要抓板去贴合,就必须先把旋转偏移量算出来,再传给运动控制卡做角度补偿。
再比如连接器针脚检测,针脚末端轻微弯曲一点点,角度偏差就可能导致插接不良。这时候视觉要做的,是把针脚边缘拟合成直线,算它的倾斜角,判断是否超出公差范围。这类需求在3C电子、锂电、汽车零部件行业里非常普遍,属于机器视觉项目里典型的“硬需求”——没有角度检测,整条线的自动化和良率管理就无从谈起。
1.2 拿到一个角度定位需求,先想清楚四件事
很多新手拿到项目就直接开始读图、找算子,容易被带偏方向。我一般建议先做一轮需求拆解,哪怕只是在脑子里过一遍。核心是四个问题:
第一,检测对象到底是什么。你测的是工件轮廓的整体旋转角,还是某个特征边的倾斜角,还是两条边之间的夹角?这三种对应完全不同的算法路线。整体旋转角用模板匹配最顺手;单条边倾斜角用直线拟合;两条边夹角则需要拟合两条直线再算几何关系。对象没搞清楚,后面调参就是无头苍蝇。
第二,精度要求是多少。角度精度要求0.5度和0.01度,方案完全不是一个量级。0.5度级别,普通的形状模板匹配配好打光基本能做到;0.01度级别,就要考虑亚像素边缘提取、高分辨率相机、甚至专用标定和重复性评估。先定精度,再定相机和算法。
第三,节拍要求。产线要求一个检测周期是200毫秒还是2秒,直接决定你模板匹配的金字塔层数、搜索角度范围、搜索步长怎么设。节拍越紧,算法上越要舍得给搜索空间瘦身。
第四,环境条件。光照是否稳定、工件表面是否反光、来料一致性好不好、振动大不大。这些因素不影响算法选择,但直接影响打光方案和模板鲁棒性。很多实验室里跑得好好的项目,一上产线就疯狂误判,80%都是环境变量没兜住。
1.3 本文实战项目的基本设定
为了让这次复盘有具体抓手,我设定一个典型的检测场景:一个矩形金属工件,表面有定位孔和非对称特征标记,相机固定向下拍摄,视野内工件允许出现10度以内的旋转偏差。项目目标非常明确——输出工件相对于模板的旋转角度,精确到0.1度,同时给出定位中心坐标,供下游机械手抓取校正。
这个场景不算复杂,但麻雀虽小五脏俱全,角度测量、模板匹配、仿射变换、精度验证都会用到。后面所有的原理、代码和踩坑记录,基本都围绕这个场景展开。
2. 方案选型:模板匹配、直线拟合还是特征几何法
2.1 角度在图像里到底是怎么被“测”出来的
要理解角度检测,先理解图像里的“角度”是什么。Halcon处理的是像素矩阵,图像没有天然的“物理角度”,角度是在特征层面上定义出来的。模板匹配的做法,是把预先保存的标准模板图,在输入图像的不同位置、不同旋转角度下逐层搜索,找到相似度最高的那个状态,这个状态的旋转量就是工件的偏转角。直线拟合的做法则是直接提取工件边缘的亚像素坐标,把边缘点拟合成直线,再根据直线的斜率换算角度。
两者的共同点是:角度一定来自“特征的姿态变化”,而不是凭空测出来的。所以不管用哪种方法,前提都是图像里得有足够清晰、稳定的特征。特征不清晰,算法再花哨也白搭。
2.2 三种主流思路的对比与选型建议
实际项目里,角度检测常用的有三条技术路线。我整理了一个对照表,方便大家直接参考:
| 方案 | 核心算子 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 形状模板匹配 | create_shape_model / find_shape_model | 抗噪强、亚像素精度、能同时输出位置和角度 | 需要制作模板、受角度搜索范围限制、非对称性不足时容易误匹配 | 工件整体旋转角定位,产线上最常见 |
| 直线拟合 | edges_sub_pix + fit_line_contour_xld | 实现简单、直观、适合测量单边倾角 | 对边缘质量要求高,光照变化容易导致拟合结果漂移 | 针脚倾斜、毛刺角度、直线边缘夹角测量 |
| 特征几何法(Blob+最小外接矩形) | threshold + smallest_rectangle2 | 速度极快、思路简单 | 精度低,受分割质量影响大 | 简单规则工件、对精度要求不高的粗定位 |
从我的经验看,优先选形状模板匹配。原因很简单:它能一次性输出行坐标、列坐标、角度和匹配分数,相当于把定位和测角度一起解决了;而且Halcon的形状模板匹配基于边缘轮廓,对光照变化和背景干扰的容忍度明显高于单纯的分割加矩形拟合。
直线拟合也不是没用,它更适合“测量角度”而不是“定位角度”。比如你要测的是产品本身某条边的角度值是否合格,而不是测整个产品偏转了多少,那模板匹配反而绕远路了。本项目的核心目标是定位旋转角,所以主方案选模板匹配;最后我会补充一段直线拟合的实现思路,方便大家按场景切换。
2.3 角度单位与坐标系:一上来就踩的暗坑
Halcon新手最容易在坐标方向、角度单位上翻车,这里必须单独拿出来讲。Halcon的图像坐标系是:行坐标row向下增长,列坐标column向右增长,默认角度单位是弧度,且逆时针方向为正。这意味着什么?在机械坐标系里,x轴向右、y轴向上、逆时针是正方向;但图像坐标系y轴是向下的,所以从图像坐标映射到机械坐标时,角度的正负方向可能要对调。
另外,find_shape_model返回的angle是弧度,项目输出角度时一般都要转成度。用tuple_deg算子一行搞定。如果后续要和运动控制卡对接,还要进一步确认对方要的角度单位是度还是脉冲数、是顺时针为正还是逆时针为正。这些细节在程序里可能就是一行代码的事,但对不了的话,机械手就会转反方向,出现“越调越乱”的现场事故。
3. 手把手实操:模板匹配法检测工件旋转角度的完整过程
3.1 图像采集与环境准备
我用Halcon的HDevelop做算法原型开发。实际项目中,图像采集源可能是工业相机、本地图片或仿真图。原型验证阶段,我建议直接用现场保存的图片做离线调试,这样复现问题最方便,比对着相机实时调要省心得多。
* 读取一张现场采集的工件图像 read_image (Image, 'workpiece_01.png') * 为了减少计算量,可先用相机内部参数做畸变校正(此处略)这里有个容易被忽略的点:做角度定位的相机,镜头畸变校正很重要。如果镜头畸变明显,画面边缘的图形会被拉伸或压缩,模板匹配在画面中心精度还行,一到边缘角度就会偏。项目要求0.1度时,畸变造成的误差可能就是0.2度以上。所以正式项目里,建议在模板匹配之前先做标定或至少做畸变校正。
3.2 ROI选取与模板制作
模板制作的成败,直接决定整个项目的上限。ROI框选的核心原则只有一个:尽量包含足够多的非对称特征。我见过很多新手直接框工件最大外轮廓,结果工件形状接近矩形,180度旋转后轮廓几乎一样,模板匹配时直接出现两种角度结果,根本无法判断到底转了多少度。
以我的矩形金属工件为例,我会把ROI选在包含定位孔和角落防错凹槽的区域,这样模板就有了明显的方向性。
* 手动框选ROI,也可以用draw_rectangle1在图像窗口里交互选取 gen_rectangle1 (ROI, 200, 300, 600, 700) reduce_domain (Image, ROI, ImageReduced) * 创建形状模板 create_shape_model (ImageReduced, 'auto', -0.39, 0.78, 'auto', 'auto', 'ignore_local_polarity', 5, 10, ModelID)这里create_shape_model的输入乍看很抽象,实际拆开看就清晰了:第一个参数是减域后的模板图像;第二个参数金字塔层数选’auto‘让Halcon自动决定;第三、四个参数对应角度搜索范围,我这里设置的是从-0.39弧度到+0.39弧度,约等于正负22度。因为工件来料旋转偏差在10度以内,留出一点余量就够了。角度范围给得越小,匹配速度越快,误匹配概率也越低。
第五个参数’auto‘是角度步长,第六个’auto‘是优化方式,第七个’ignore_local_polarity‘表示忽略局部极性变化,适合表面对比度可能发生局部反转的金属件。第八个参数5是轮廓对比度阈值,第九个10是最小轮廓对比度。后面这两个参数如果不好理解,选’auto‘即可,等匹配不稳再回来调。
3.3 核心参数逐项拆解:为什么这么设
很多同学复制代码就跑,跑不通就改参数,但并不知道每个参数背后的逻辑。这里重点讲三个直接影响角度检测质量的参数。
第一个是金字塔层数NumLevels。它的作用相当于“先粗看,再细看”。高层金字塔先在大尺度上快速定位候选区域,再往底层做精细化匹配。层数越多,速度越快,但层数过高会丢失细节,导致弱特征在顶层被滤波掉,匹配不到。项目里常见问题是模型太小或对比度太低,层数设多了反而不稳定。这时候把NumLevels从’auto‘改成手动指定,比如3或4,往往能救回来。
第二个是角度搜索范围和角度步长AngleStep。搜索范围越大,耗时越长,且可能带来误匹配;步长越细,精度越高,但耗时直线上升。Halcon的’auto‘模式会自动平衡速度和精度,但如果项目对角度精度有硬指标,建议手动指定一个合理步长,比如0.01度级别时设置角度步长为0.005弧度左右,再在匹配时配合亚像素插值。我的经验是:大部分0.1度精度项目,’auto‘步长够用;真正需要0.01度时,与其死磕步长,不如考虑提高相机分辨率,因为像素分辨率不够,步长再小也是自欺欺人。
第三个是对比度参数Contrast和MinContrast。它们控制模板提取哪些边缘点。设置太高,模板特征太少,容易丢失工件上的关键轮廓;设置太低,又把噪声和纹理当特征收进来,匹配时容易被干扰。金属工件表面如果有拉丝纹理,最容易在这里翻车。建议用’auto‘跑一遍,再用inspect_shape_model查看模板轮廓,确认提取出的特征是否集中在工件的几何边缘上。
3.4 找模板并输出角度
模板建好后,接下来就是在每张待测图上找模板。
* 在待测图像中查找模板 find_shape_model (Image, ModelID, -0.39, 0.78, 0.5, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score) * 将弧度角度转换为度 AngleDeg := tuple_deg(Angle) * 将角度归一化到0到360度范围,便于业务显示和后续判断 if (AngleDeg < 0) AngleDeg := AngleDeg + 360.0 endiffind_shape_model的参数我按顺序解释:ModelID是模板句柄;第二、三个参数是搜索角度范围,必须和创建模板时的范围一致;第四个参数0.5是最低匹配分数,低于0.5的候选一律不要;第五个1是匹配个数,这里只找最优的一个;第六个0.5是最大重叠率,用于多目标场景防止重复输出;第七个’least_squares‘是亚像素精度优化方式,求角度必须用它,否则输出角度只有步长级别的分辨率;第八个0是轮廓对比度阈值,设为0表示不额外限制;第九个0.9是金字塔层数参数,表示在最高层开始搜索;输出的Row、Column是定位中心,Angle是弧度角,Score是匹配分数。
这里有个非常关键的实战心得:Angle输出的是模板在图像坐标系下的旋转量,默认范围是-pi到pi,也就是-180度到180度。很多场景下业务侧希望看到0到360度,或者-90度到90度,所以输出角度后一定要做一次业务域的归一化。上面代码里我做了最简单的负角度加360处理,实际项目里建议写成公共函数,统一管理角度换算逻辑。
3.5 从“测出角度”到“修正定位”:仿射变换
如果只是要输出角度报表,到上一步就结束了。但如果视觉要给机械手纠偏,还必须把角度和坐标转换成机械手能用的偏移量。这里就要用到仿射变换。
* 构造一个刚体变换:从模板基准位置旋转到当前匹配位置 vector_angle_to_rigid (RowRef, ColumnRef, AngleRef, Row, Column, Angle, HomMat2D) * 使用仿射变换把模板坐标系下的任意点坐标映射到当前图像坐标 affine_trans_point_2d (HomMat2D, PointRow, PointCol, MappedRow, MappedCol)这段代码的逻辑是:模板创建时记录一个参考点(比如工件的抓取中心)和参考角度。现场找到工件后,用vector_angle_to_rigid得到一个变换矩阵HomMat2D,这个矩阵描述的就是“从标准位置到当前实际位置”的旋转和平移。之后任何在标准位置上定义的抓取点、检测点,都可以通过affine_trans_point_2d映射到当前图像上,得到实际的物理位置。
这步一做,视觉输出的就不只是角度,而是一整套“位置补偿量”,运动控制直接按这个补偿走位就行。很多现场联调扯皮的问题,比如机械手抓不到、抓偏了,根源往往是只给了角度没给补偿中心,或者中心坐标没有跟着角度一起旋转。仿射变换一套下去,中心和角度是联动的,机构动作自然就对了。
3.6 直线拟合补充:不建模板怎么测角度
模板匹配不是万能的。有时候工件来料种类多、换型频繁,每换一种就要重新建模板,现场维护人员觉得麻烦。或者想测的不是整体旋转角,而是某一条边的倾斜角,这时候直线拟合更直接。
* 亚像素边缘提取 edges_sub_pix (Image, Edges, 'canny', 1.5, 20, 40) * 选择长度最大的边缘轮廓(通常是工件主导边) select_contours_xld (Edges, SelectedContours, 'length', -1, 200, -0.5, 0.5) * 拟合直线 fit_line_contour_xld (SelectedContours, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist) * 根据直线方向向量计算角度 LineAngle := atan2(RowEnd - RowBegin, ColEnd - ColBegin) LineAngleDeg := tuple_deg(LineAngle)这里的原理是:边缘上的点经过亚像素提取后,坐标精度可达0.1像素甚至更高,把这些高精度点拟合成直线后,直线斜率换算的角度精度通常优于模板匹配。但也正因为它依赖边缘点,如果打光不均匀导致边缘断裂、重影,拟合出来的直线角度会飘。我的建议是:直线拟合适合作为“标定和测量”手段,而模板匹配更适合“定位和引导”;两者配合使用,效果最好。
4. 从实验到落地:精度验证与稳定性提升
4.1 精度验证怎么做:重复性、绝对精度和GRR
角度检测项目交付前,最怕的就是拍脑袋说“应该准”。规范做法是拿同一批工件做两类验证。第一是重复性验证:取同一个工件,放到视野内同一个位置,连续触发视觉检测30次,记录30个角度值,算标准差。标准差小于你验收精度的一半,基本算合格。第二是绝对精度验证:把工件放上高精度旋转台,从0度开始每次转1度,记录视觉测量值,和旋转台实际角度做差值,画一条误差曲线,看最大偏差是多少。0.1度验收的项目,最大偏差最好控制在0.05度以内。
我见过不少项目,重复性很好,标准差只有0.005度,但绝对精度差得离谱,一查原因发现是镜头畸变没校正,或者工件表面本身就不是完好的平面。所以说,重复性反映的是系统稳定性,绝对精度反映的是系统准确性,两个都测,心里才有底。
4.2 打光方案对角度检测稳定性的影响
角度检测本质上是靠边缘或轮廓特征来算的,所以打光直接决定边缘的锐度和一致性。同一种工件,用前光源、背光源、同轴光,出来的角度检测稳定性完全不一样。
高角度环形光适合表面光滑工件,边缘对比度高,但也容易产生反光和过曝;低角度光能突出表面凹凸纹理,适合表面有细微特征的产品,但环境光干扰影响比较大;同轴光适合高反光金属表面,能抑制反光斑,但对工件表面的平整度比较敏感。
我的经验是:角度检测项目打光追求的不是亮度,而是“边缘的一致性”。白天一个样、晚上一个样,或者工件位置稍微偏一点,边缘灰度就大幅变化,那再好的算法也扛不住。所以在打光验证时,一定要刻意测试工件在视野边角位置时的图像质量,别只在视野中心测。
4.3 多目标同时测角度:匹配个数与排序逻辑
有些场景一个视野里同时放多个工件,比如一盘排料上有20个位置,每个位置都可能有工件旋转偏移。find_shape_model支持一次性返回多个匹配结果。
find_shape_model (Image, ModelID, -0.39, 0.78, 0.5, 20, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score)第四个参数1改成20,就表示最多找20个。但找回来的结果是按分数从高到低排的,不一定按视野里的物理位置排。很多项目需要按“从左到右、从上到下”的工艺顺序输出,所以拿到结果后,建议根据Row和Column做一个自定义排序,再顺序处理。
多目标场景里还要额外注意一个参数:最大重叠率MaxOverlap,就是代码里的0.5。这个参数控制两个匹配结果的重叠程度,设太小会把密集排列的相邻工件漏掉,设太大会在同一工件上输出多个重叠结果。多目标密集排布时,建议从0.5开始试,结合现场工件间距微调。
4.4 算法耗时优化:争取每一毫秒
产线节拍是硬指标。模板匹配本身已经是相对成熟高效的算法,但参数设置不当也会让耗时翻好几倍。最影响耗时的三个因素:搜索角度范围、金字塔层数、匹配个数。
我把一个具体项目的优化过程拿出来分享。项目要求200毫秒内完成,但原始配置下匹配一次需要350毫秒。排查后发现,角度搜索范围给的是-180度到180度,实际工件最大偏转不超过10度。把搜索范围缩到正负15度后,耗时直接降到110毫秒;又把金字塔层数从自动改成4,耗时降到65毫秒。所以节拍不够的时候,先砍搜索范围,再调金字塔,不要一上来就想着换GPU或换工控机。
另外,Halcon多线程也值得用。比如一个画面里需要检测多个不同区域的工件角度,可以把几个find_shape_model分到不同线程执行。Halcon的算子本身是线程安全的,但要注意每个线程独立的句柄和参数传递,避免共享内存冲突。
5. 高频实战问题与排查技巧实录
5.1 角度在0度和360度之间跳变
这个问题出现频率极高。工件实际只转了2度,但输出角度一会儿是2度,一会儿是358度,甚至有个别帧直接显示-2度。原因是角度本身是个周期量,0度和360度其实是同一个姿态,但Halcon输出的角度范围是-pi到pi,做了一次截断,导致同一姿态在不同帧里可能落在正负区间的不同侧。
解决办法是固定一个归一化规则,比如统一归一到0到360度,或者统一归一到-90度到90度。更稳妥的做法是:设定一个参考角度基准值,比如模板角度是5度,匹配出来的角度如果和基准值相差超过180度,就对它做加减360度调整,让输出始终落在基准值的连续区间内。这样角度就不会“跳”了。
5.2 对称工件出现两种角度结果
工件本身接近中心对称,比如很多圆形端盖、正方形垫片,旋转180度后轮廓几乎看不出差异。模板匹配会在两个角度上都给出高分,于是有时输出30度,有时输出210度,结果完全不可用。
解决思路有两个方向。一是改模板,把ROI尽量框住非对称特征,比如防错孔、定位销、丝印,迫使模板在旋转180度后不再相似。如果工件表面实在没有非对称特征,那就要从治具端考虑,物理防错,让工件只有一种放法。二是程序里增加逻辑判断,用额外的特征确认方向。比如先用模板匹配粗定位,再在小范围内用直线拟合验证某个局部特征的偏置方向,从而消解180度歧义。这里有个经验之谈:模板设计花10分钟,可能比在代码里写5个if判断更省事。
5.3 匹配成功率突然下降或分数变低
现场最怕的是上午跑得好好的,下午开始疯狂报错。大部分情况不是算法变了,而是环境变了。比较常见的原因:光照强度漂移(太阳光、相邻设备灯光干扰、光源老化)、工件表面有油污或遮挡、相机镜头起雾。
排查思路有一个顺序:先保存现场异常图,把当前帧图像保存下来离线复现,别让产线停在那里干等;然后对比异常图和正常图的灰度直方图,看整体亮度是不是偏了;接着把MinScore阈值临时调低,看是不是分数整体下降,还是存在部分帧完全匹配不上;最后检查硬件,光源是不是衰减了、镜头是不是脏了。我踩过最离谱的一次坑,是车间换了新的节能灯,频闪正好和相机曝光频率打架,导致每几帧就有一帧图像亮度异常,角度数据周期性跳变。后来换了直流光源供电,问题才彻底消失。
5.4 角度测量精度达不到要求
如果算法和打光都没问题,但精度就是差一点,先看相机分辨率是否够。角度的极限精度受像素分辨率限制,视野比如是100毫米宽,相机像素是2048,那一个像素对应约0.05毫米;如果特征点定位精度是0.1像素,能分辨的角度还要看特征点之间的距离。特征点离旋转中心越远,同样像素误差对应的角度误差越小。所以提高精度最直接的手段,除了加分辨率,就是让模板特征尽量分布在工件外缘,远离旋转中心。
如果直线拟合的角度精度不够,可以试试把fit_line_contour_xld的加权方法从’least_squares‘改成’tukey‘。后者对边缘噪声点更鲁棒,在边缘有毛刺的场景里,角度测量精度能明显提升。
5.5 Halcon与C#/C++集成时的常见坑
算法原型在HDevelop里跑通只是第一步,项目落地总要把算法封装进上位机软件。Halcon最常用的集成方式是C#调用HalconDotNet,或者QT里用C++调用类型。集成时最常见的坑有三个:一是HDevelop脚本里图片路径是写死的,上线后必须改成相机实时采图,路径问题要提前清理;二是HDevelop和运行时性能差异大,HDevelop里跑20毫秒,C#里一跑50毫秒,多半是每次调用都重复创建了模板或重复初始化了资源,模板应该只在程序启动时加载一次,运行时反复调用find_shape_model;三是运行时License问题,Halcon是商业授权软件,正式部署需要购买对应的运行时授权,很多项目在联调阶段疏忽了这一点,导致上线前紧急处理。
C#里一个最小调用结构大致是:创建HTuple承载参数,用HOperatorSet调用算子,结果也是HTuple类型。核心思路和HDevelop完全一致,只是多了资源释放和异常处理的代码。如果你刚接触这块,建议先用Halcon自带的“导出为C#函数”功能生成代码,再在此基础上改造成自己的业务逻辑,比自己从头写要快得多。
6. 项目经验扩展:角度检测思路还能怎么用
6.1 在主流行业里的延伸场景
角度检测这套底层能力,换一个外壳就能用到很多行业。在3C电子里,手机中框的贴合引导、摄像头模组的旋转校准,本质上就是模板匹配加角度输出;在锂电行业,极片的裁切角度、电芯入壳前的姿态确认,也是同一套逻辑;在汽车零部件里,油封的唇口角度检测、涡轮叶片安装角测量,则更偏向直线拟合和边缘测量。换行业不换内核,核心都是“把角度这个几何量从图像里稳定地算出来”。
建议做项目的时候,把这套角度换算、归一化、仿射变换的代码沉淀成公司内部的公共工具库。今天我写的这些逻辑,实际上就是基于这个思路反复迭代出来的,每做一次项目就删掉一批不合理的硬编码,换成公共函数,后续新项目复用时,效率和可靠性都会高一个台阶。
6.2 与Halcon深度学习的结合方向
现在Halcon的深度学习工具已经很成熟,很多时候可以把传统视觉和深度学习结合起来,各干各擅长的活。比如用深度学习做工件型号分类和粗定位,再用传统模板匹配做高精度的角度输出;或者用深度学习分割出工件的关键区域,把分割结果的mask作为ROI去引导传统算子做精确测量。深度学习解决的是“是什么、大致在哪”的问题,传统视觉解决的是“精确多少度、精确多少像素”的问题,两者结合,项目的鲁棒性和精度都能兼顾。后续有时间,我也会专门写一篇关于这两种方法如何在一个项目里协同工作的实战记录。
说回角度检测这件事,我在实际项目里体会最深的一点是:角度问题90%都能用模板匹配加一个归一化函数解决,剩下的10%才是精度极限和特殊特征的问题。做这一类项目时,先把坐标系搞对,再定好角度归一化规则,最后处理模板特征和打光,流程走顺了,项目基本不会卡壳。希望这篇记录能给你提供一条清晰的路线,下次拿到“检测定位角度”的需求,直接按这个思路往下推就行。