项目场景:使用coco数据集进行目标检测遇到一个深拷贝的问题
使用yolo作目标检测,读取的coco数据集,数据格式是这样的:
-train
-annotations
-instances_train2017.json
-image
-image_name_1
-…
json中的格式为:
{‘info’:
“license”:
“images”:按照图像id排序,包含图像名称及图像长宽
“anncotations”:按照目标类别排序,包含图像id及目标框数据等数据
“categories”:类别数据
}
训练中创建traing_dataloader,返回图像resize的图像数据,resize后对应的标签((中心点坐标)x,y,w,h),对应的类别标签。
dataset创建在这篇博客基础上进行修改:https://blog.csdn.net/haohulala/article/details/109013078
getitem中有这样的语句
def __getitem__(self, index):
img, ann = super().__getitem__(index)
# 过滤掉"iscrowd"不为0的属性
ann = [o for o in ann if(o["iscrowd"]==0)]
# 获得bbox
bbox = [o["bbox"] for o in ann]
bbox = np.array(bbox, dtype=np.float32)
# 将bbox的坐标由 xywh的性质转变为x1y1x2y2
bbox[..., 2:] = bbox[..., 2:] + bbox[..., :2]
我改为了这样
# 将bbox的坐标由 xywh的性质转变为中心点,w,h
for i in bbox:
i[0] = int(i[2]/2)+i[0]
i[1] = int(i[3]/2)+i[1]
问题描述
训练过程中遇到问题,在第一个epoch时正常运行,到第二个epoch时总是出现框标签超出图像大小的错误
File "E:\PycharmProjects\other\111\YOLOv3_PyTorch\training\..\nets\yolo_loss.py", line 136, in get_target
noobj_mask[b, anch_ious > ignore_threshold, gj, gi] = 0
IndexError: index 16 is out of bounds for dimension 3 with size 13
原因分析:
经过我在不同位置打印信息,定位到了上述bbox坐标转换的位置,有经过不同epoch的不断调试,发现了问题。因为bbox是直接赋值来的,在对bbox的值进行变换的时候,原始数据也被改变了,所以到第二个epoch时bbox就被变换了两次。导致超出范围。
解决方案:
- 不要在__init__中读取数据,只进行path的赋值,在getitem中再读取数据,但是我使用的coco数据格式是,所有数据都再一个文件中,每次读取都必须将所有数据全部读一遍,所以效率很低。
- 使用深拷贝赋值bbox
# 获得bbox
bbox = copy.deepcopy([o["bbox"] for o in ann])