YOLO-OBB旋转角的探究

ChainPray 发布于 5 天前 23 次阅读


问题

yolo-obb模型输出的angel会限制在0-90度之间,这会导致predict的时候角度突变且obb不准确的情况

笔者接手的项目中需要用需要对目标(矩形料盘)准确识别出相对于标准纵向放置位置旋转的角度,然后用这个角度去控制机械臂旋转

但是yolo-obb输出值明显有问题,我们数据集严格按照物体左上开始顺时针标记4个点位置来标准,但是放到yolo-obb中训练出来的模型预测的时候不仅rotate angel只有0-90,width和height也会在某个位置之后交换

探究

首先放个颇有启发的issue

xyxyxyxy2xywhr 输入格式 (增强? ·问题 #19799 ·Ultralytics/Ultralytics(超溶解剂)

官方的obb训练的时候输入的数据集是4点xy坐标的格式而不是(x,y,w,h,r),官方文档上也说明了“在内部处理成xywhr”,可以明确的是yolo内部转换数据格式的时候算法不合理,没有考虑到4点标注的顺序

在ultralytics官方仓库下ultralytics/utils/ops.py中我们可以发现yolo内部转换(x1,y1,x2,y2,x3,y3,x4,y4)格式数据到(x,y,w,h,r)的时候使用的是cv2的库函数minAreaRect

这个库函数存在一个明显的问题是不会考虑四点顺序,给定四个点不论什么顺序都会返回包含给定点集的最小面积旋转矩形,旋转角固然也就是0-90了(实际是-90-0,差不多)

但是直接修改xyxyxyxy2xywhr也有点问题,因为这里传入的参数pts是yolo在初始化数据集的时候重采样过的,也就是输入时候的4个点被yolo采样成了多个点作为pts输入cv2库函数计算最小包围矩形框

所以首先需要关闭yolo的重采样,将ops.py中的resample_segments函数中的所有内容注释掉,仅保留return

这样在xyxyxyxy2xywhr函数中获得的pts就是包含4个点的4*2numpy数组,直接通过0,1点和1,2点距离计算w,h;根据点0到点1的向量计算旋转角r,范围(-pi,pi)

这个时候又发现了新的问题,出现了两个点的x轴数值竟然一样,并且画图出来无法构成矩形;这里怀疑是yolo在预处理的的时候将出界的直接移动到图像边框内。

这个问题的解决方案笔者采用的是关闭yolo训练自带的数据增强(主要是平移和旋转);同时在数据标注和生成的时候保证编竹框没有超出图像

做到这一步发现训练的时候没有问题可以正常收敛,但是预测的时候预测框经常突变,这个问题是obb在predict的时候会调用ops.py下的regularize_rboxes函数,这个函数会对角度取模并交换宽高

把这个函数的内容注释掉就能正常预测了,角度在-90~90之间。

最后笔者还在head.py的OBB类的forward方法中吧angel处理的代码改了一下,源代码是将angel缩放到[-pi/4, 3pi/4]上,笔者改成了缩放到[-pi/2, pi/2]上,虽然仍未探明这个修改的作用

深圳大学腾讯创新俱乐部的一名TICer,目前致力于成为全栈工程师
最后更新于 2025-04-28