效果图
COCO关于目标大小的定义
小目标的两个特点
1.数据集中包含小物体的图片相对较少,这可能会使任何检测模型更倾向于关注中等和大型物体。
2.小物体所占面积较小,意味着小物体位置的缺乏多样性。
解决方案
我们通过对包含小物体的图片进行过采样来解决第一个问题。我们通过在每个包含小物体的图像中多次复制粘贴小物体来解决第二个问题。在复制粘贴每个物体时,我们确保粘贴的物体不与任何现有物体重叠。这增加了小物体的位置多样性,同时确保这些物体出现在正确的上下文中。
copy-paste增加锚框数量。
操作细节
在将对象粘贴到新位置之前,我们对其进行随机变换。我们通过更改物体大小±20%来缩放物体,并将其旋转±15◦。我们只考虑未遮挡的对象,因为将分离的分割掩码分别插入中间未曾见过的部分通常会导致不太逼真的图像。我们确保新粘贴的对象不与任何现有对象重叠,并且距离图像边界至少有5个像素。
我们测试了三种设置。在第一种设置中,我们用复制和粘贴小物体后的图像替换每个带有小物体的原始图像。在第二种设置中,我们复制这些增强图像以模拟过采样。在最后一个设置中,我们保留原始图像和增强后的图像,这相当于将带有小物体的图像过采样两倍,并将复制的副本增加更多的小物体进行增强。
复制和粘贴小物体有不同的方法。我们考虑了三种单独的策略。首先,我们选择一张图像中的一个小物体,并在随机位置复制和粘贴多次。第二,我们选择多个小物体,并将每个小物体粘贴到任意位置。最后,我们将每个小物体在图像中复制和粘贴到多个随机位置。在所有情况下,我们使用上面的第三种增强设置;也就是说,我们保留原始图像和其增强副本。
在粘贴小物体的副本时,有两件事需要考虑。首先,我们必须决定粘贴的对象是否会与任何其他对象重叠。虽然我们选择不引入任何重叠,但我们通过实验证明了它是否是一个好策略。其次,进行平滑处理以使得粘贴对象的边缘更加平滑是一个设计选择。我们尝试使用不同的高斯滤波器大小进行平滑处理,以帮助提高性能。
结论
训练模型对“粘贴”小物体进行了有效的过拟合,但不一定对原始小物体进行了过拟合。我们认为这是由于粘贴造成的伪影,例如不完美的对象掩码和与背景的亮度差异,相对容易被神经网络检测到。最好的结果是通过将过采样和概率为p = 0.5的增强(原始+增强)与原始和增强小物体的比率为2:1相结合来达到的。这种设置产生了比单独进行过采样更好的结果,确认了粘贴小物体所提出的策略的有效性。
代码实现
import aug as am
import Helpers as hp
from util import *
import os
from os.path import join
from tqdm import tqdm
import random
base_dir = os.getcwd()
save_base_dir = join(base_dir, 'save')
check_dir(save_base_dir)
#train.txt存放需要粘贴的图像的位置
imgs_dir = [f.strip() for f in open(join(base_dir, 'train.txt')).readlines()]
labels_dir = hp.replace_labels(imgs_dir)
#small.txt存放粘贴图像的位置
small_imgs_dir = [f.strip() for f in open(join(base_dir, 'small.txt')).readlines()]
#打乱存放被粘贴的图像的顺序
random.shuffle(small_imgs_dir)
for image_dir, label_dir in tqdm(zip(imgs_dir, labels_dir)):
small_img = []
#搞八个小目标图像出来
for x in range(8):
if small_imgs_dir == []:
#exit()
small_imgs_dir = [f.strip() for f in open(join(base_dir,'small.txt')).readlines()]
random.shuffle(small_imgs_dir)
small_img.append(small_imgs_dir.pop())
am.copysmallobjects2(image_dir, label_dir, save_base_dir,small_img)
接下来主要是copysmallobjects2这个函数的调用
def copysmallobjects2(image_dir, label_dir, save_base_dir, small_img_dir):
image = cv2.imread(image_dir)
labels = read_label_txt(label_dir)
if len(labels) == 0:
return
rescale_labels = rescale_yolo_labels(labels, image.shape) # 转换坐标表示
all_boxes =