dataset = LoadImages(source, img_size=img_size)
dataset = LoadImagesAndLabels(path, img_size, batch_size, rect=False, single_cls=opt.single_cls)
# 此处我为了直接对比 detect 和 test 将 rect 默认设为了 False
LoadImages会默认使用Auto参数减少pad量,将pad控制在64以下。
而LoadImagesAndLabels会默认禁用Auto,并且将scale_up参数改为由参数augment操控,
后者仅对小图有不同效果,而前者会导致此处会导致输入网络的图片大小不同
所以将LoadImagesAndLabels中的letterbox调用改为了:
img, ratio, pad = letterbox(img, shape, auto=True, scaleup=True)
图片本体会被缩小1个像素,对于小目标影响明显。
将有问题的那一行修改成这样就好了:
img = cv2.resize(img, (int(round(w0 * r)), int(round(h0 * r))), interpolation=interp)
result.json
来自detect自写代码直接输出的结果
检查发现,两者在调用scale_coords函数上存在区别,
detect未传入ratio_pad参数,test使用数据集中的过来的shape作为ratio_pad。
在第一个if中,detect走的是第一条路直接根据长边计算gain,再计算pad
在test中,此时如果shape[0][0]不等于shape[0][1],两者的gain计算就会出现偏差,
而shape[0][0]正是高度方向的shape。
def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None):
# Rescale coords (xyxy) from img1_shape to img0_shape
if ratio_pad is None: # calculate from img0_shape
gain = max(img1_shape) / max(img0_shape) # gain = old / new
pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2 # wh padding
else:
gain = ratio_pad[0] # 在此处读取整个shape[0]
pad = ratio_pad[1]
coords[:, [0, 2]] -= pad[0] # x padding
coords[:, [1, 3]] -= pad[1] # y padding
if ratio_pad is None:
coords[:, :4] /= gain
else:
coords[:, [0, 2]] /= gain[1] # 在此处分别对x和y进行缩放
coords[:, [1, 3]] /= gain[0]
clip_coords(coords, img0_shape)
return coords