Yolo中OBB的角度范围和角度损失设计思路
确定标签和网络输出box的角度范围
- 输出 ultralytics/nn/modules/head.py
class OBB(Detect):
...
def forward(self, x):"""Concatenates and returns predicted bounding boxes and class probabilities."""bs = x[0].shape[0] # batch sizeangle = torch.cat([self.cv4[i](x[i]).view(bs, self.ne, -1) for i in range(self.nl)], 2) # OBB theta logits# NOTE: set `angle` as an attribute so that `decode_bboxes` could use it.angle = (angle.sigmoid() - 0.25) * math.pi # [-pi/4, 3pi/4]
forward中可以观察到angle返回的弧度在-pi/4, 3pi/4
- 标签 ultralytics/utils/ops.py
def xyxyxyxy2xywhr(corners):is_torch = isinstance(corners, torch.Tensor)points = corners.cpu().numpy() if is_torch else cornerspoints = points.reshape(len(corners), -1, 2)rboxes = []for pts in points:# NOTE: Use cv2.minAreaRect to get accurate xywhr,# especially some objects are cut off by augmentations in dataloader.(x, y), (w, h), angle = cv2.minAreaRect(pts)rboxes.append([x, y, w, h, angle / 180 * np.pi])return (torch.tensor(rboxes, device=corners.device, dtype=corners.dtype)if is_torchelse np.asarray(rboxes, dtype=points.dtype)) # rboxes
经过cv2.minAreaRect(pts)会得到0, pi/2
可以发现标签和网络输出是包含关系,即输出范围包含了标签范围
预测时肯定也是使用0, pi/2,具体可细节可以参考这篇博客
如何获得角度
- ultralytics/utils/metrics.py
- 在def probiou(obb1, obb2, CIoU=False, eps=1e-7)中可以得到obb
- 添加如下代码即可以得到预测和输出对应的角度
obb1_angels, obb2_angels = obb1[:, -1] * 180 / np.pi, obb2[:, -1] * 180 / np.pi
- 如果你想添加角度损失可以在这里加,角度损失添加方法有很多,可以参考这个算是其中一种方法
添加时注意的问题
-
通常会对弧度通过sin、cos计算
-
那么就要考虑周期性问题,例如现在标签是0-pi/2而sin、cos函数周期性是2pi,那么在设计损失时就要将其映射到0-2pi,这样就能避免60、30度这种sin(60)+cos(60)=sin(30)+cos(30)的问题
-
损失函数可以采用常见的均方误差
-
主要是提供一种思路,更好的理解OBB的角度范围、如有需求后续设计损失的思路
-
另一种方法通过改善iou损失优化角度问题
-
就不把别人的成果整理发布了,想要优化旋转框问题看上面链接就行