一、问题
当时在调试装甲板配对的时候,发现一直报错。因为我封装和检测逻辑每一步都会有打印报错日志,但我看我的 inRange 后的图片,发现是没有问题的;mask 后的图片我也看了,也标记了,还把坐标打印出来,但发现还是有问题。最后才怀疑角度有问题。
二、排查
然后我把每一个的坐标和角度都打印出来,把对应坐标和角度发给 AI,让 AI 总结。根据图片上本来应该配对的,却显示角度差那么多,然后就发现问题了。
当时就想到:角度的标准是哪一个边?哪一个是宽、哪一个是高?同一个垂直灯带,为什么有时候是 180° 左右,有时候是 90° 左右呢?
角度有问题是我当时想打印出来角度的 log,来判断是不是我写的程序错了。但明明是图片上的灯带就应该配对的,我把坐标给 AI 分析,AI 说明了原因:可能是对于 minAreaRect 的 angle 判断算法有关系。
三、原因
算法对于角度的定义,是 width 这个边与 x 轴的夹角。
但程序对识别图形长宽的判断逻辑是“随机的”,不可控制的,不一定宽就是 width,也可能是 height;不一定短边就是宽、长边就是长,不一定是我们认知中的那样。需要检查和判断,所以可能是垂直的边是 width(90°),也可能是平放的边是 width(0°)。
四、解决
统一以灯带的长边为基准,计算其与 x 轴的夹角。
长边之所以是长边,就是比较 width 和 height 的大小来判断。width 是长边则不用动,否则转 90°。
floatangle=rRect.angle;if(rRect.size.width<rRect.size.height){angle+=90;// width 不是长边,转一下}// 现在 angle 就是长边与 x 轴的夹角了,统一了