最近项目用到了 yolo v5。初始图像是 1440×1080 大小的,在训练时显示 “cuda out of memory”,故保持原始长宽比,将图像缩小成 720×540 大小进行训练。问题出在检测过程。
在原始 detect.py 中,有一段定义代码:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', nargs='+', type=str, default='', help='model.pt path(s)')
parser.add_argument('--source', type=str, default='', help='source')
parser.add_argument('--output', type=str, default='', help='output folder')
parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
可以看到,yolo v5 使用 640×640 的图像进行训练和测试,这里的 img_size 定义为 640,是一个 int。
由于我的图像是 720×540,所以在测试时,我想当然地把这一行改成了
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', nargs='+', type=str, default='', help='model.pt path(s)')
parser.add_argument('--source', type=str, default='', help='source')
parser.add_argument('--output', type=str, default='', help='output folder')
parser.add_argument('--img-size', type=int, default=[720,540], help='inference size (pixels)')
这里,img_size 是一个 [720,540] 的 list。
运行 detect.py,报错 TypeError: unsupported operand type(s) for -: ‘int‘ and ‘list‘ ,通过博友针对这一问题的分析: 链接,通过 np.array() 将 list 转换为一个 array,又报错 TypeError: only size-1 arrays can be converted to Python scalars,回到 general.py,发现这么两段代码:
def check_img_size(img_size, s=32):
# Verify img_size is a multiple of stride s
new_size = make_divisible(img_size, int(s)) # ceil gs-multiple
if new_size != img_size:
print('WARNING: --img-size %g must be multiple of max stride %g, updating to %g' % (img_size, s, new_size))
return new_size
def make_divisible(x, divisor):
# Returns x evenly divisble by divisor
return math.ceil(x / divisor) * divisor
第一段代码给一个 stride = 32,并且对 img_size 进行判断,是否能被 32 整除。
关键问题就在第二段代码中,math.ceil() 是一个向上取整操作,所以要求 x / divisor 必须是一个数值,然后将其转换为 int 型。输出 x 的值,发现是 [720,540],也就是图像的尺寸,这是一个 list ,出现计算问题。
那么这个 img_size到底是什么意思呢?如果我检测的图片长宽比不是1:1,或者我的图片大小并不是32的整数倍,如果 resize 会使目标失真,怎么办呢?
通过分析,实际上这些疑问都是没有必要的。yolo v5 设置的 img_size 并不会影响任意尺寸图像的检测,这个数值设置的目的是使输入图像先被 resize 成 640×640,满足检测网络结构,最后再 resize 成原始图像尺寸,进行显示。
最后我们设置 img_size = 320 (32的整数倍),同样没有问题,验证了我们的想法。