基于PyTorch的Mask RCNN训练报错:多边形转矩形边界框失败
解决ICDAR2019 ArT多边形转矩形边界框的无效框问题
问题根源分析
你遇到的三类错误本质是标注多边形的坐标异常或计算逻辑疏漏:
- 浮点精度误差导致极值点重合,出现宽/高为0的框
- 部分标注存在全0坐标的无效多边形
- 极值计算时未确保
xmin < xmax、ymin < ymax的顺序
标准化处理方案
以下是针对8万张图像标注的批量处理逻辑,覆盖所有异常场景:
1. 核心转换函数
import numpy as np def polygon_to_valid_rect(points): # 转换为numpy数组方便计算 points_np = np.array(points, dtype=np.float32) # 过滤全0点的无效标注 if np.all(points_np == 0): return None # 提取所有x、y坐标 xs = points_np[:, 0] ys = points_np[:, 1] # 计算极值 xmin = xs.min() xmax = xs.max() ymin = ys.min() ymax = ys.max() # 修正宽高为0的情况:添加微小偏移量 eps = 1e-3 if xmax - xmin < eps: xmax += eps if ymax - ymin < eps: ymax += eps # 确保坐标顺序正确(防止max < min的异常) xmin, xmax = sorted([xmin, xmax]) ymin, ymax = sorted([ymin, ymax]) # 返回符合PyTorch要求的[xmin, ymin, xmax, ymax]格式 return [xmin, ymin, xmax, ymax]
2. 在PyTorch数据集中集成
在你基于官方教程实现的Dataset类中,替换原有的边界框转换逻辑:
import json import os from PIL import Image import torch from torch.utils.data import Dataset class ICDAR2019ArTDataset(Dataset): def __init__(self, img_dir, annotations_file, transforms=None): self.img_dir = img_dir self.annotations = json.load(open(annotations_file)) self.transforms = transforms def __getitem__(self, idx): # 加载图像和标注 img_info = self.annotations[idx] img_path = os.path.join(self.img_dir, img_info["image_id"]) img = Image.open(img_path).convert("RGB") boxes = [] labels = [] iscrowd = [] for ann in img_info["annotations"]: # 跳过 illegibility=True 的标注(可选) if ann["illegibility"]: continue rect = polygon_to_valid_rect(ann["points"]) # 跳过无效框 if rect is None: continue boxes.append(rect) labels.append(1) # 文字类别统一设为1 iscrowd.append(0) # 整理为PyTorch要求的target格式 target = {} target["boxes"] = torch.tensor(boxes, dtype=torch.float32) target["labels"] = torch.tensor(labels, dtype=torch.int64) target["iscrowd"] = torch.tensor(iscrowd, dtype=torch.int64) target["image_id"] = torch.tensor([idx]) target["area"] = (target["boxes"][:, 3] - target["boxes"][:, 1]) * (target["boxes"][:, 2] - target["boxes"][:, 0]) if self.transforms is not None: img, target = self.transforms(img, target) return img, target def __len__(self): return len(self.annotations)
3. 额外优化建议
- 对于宽高小于1像素的极小框,可以在转换函数中添加过滤逻辑(比如
if (xmax-xmin)*(ymax-ymin) < 1: return None),避免干扰模型训练 - 提前批量预处理所有标注文件,过滤无效项并保存结果,减少训练时的实时计算开销
验证示例
针对你提供的"red"标注,转换后的矩形框为:[19.896204045991865, 92.58403315228024, 63.3249196091766, 110.16062344395255]
宽高均为正数,坐标顺序正确,完全符合Mask RCNN的输入要求。
内容的提问来源于stack exchange,提问作者Leon
相关产品推荐
相关产品推荐

